Почему мой запрос с префиксным поисковым префиксом чувствителен к регистру, несмотря на использование строчных фильтров для индекса и поиска? - PullRequest
0 голосов
/ 16 мая 2018

Проблема

Я работаю над автозаполнением, используя ElasticSearch 6.2.3. Я бы хотел, чтобы результаты моего запроса (список страниц с полем «Имя») были упорядочены с использованием следующего приоритета:

  1. Соответствие префикса в начале «Имени» (запрос префикса)
  2. Любое другое точное (целое слово) совпадение в пределах «Имя» (термин запроса)
  3. Нечеткое совпадение (в настоящее время это делается в поле, отличном от имени, с помощью токенайзера ngram ... поэтому я предполагаю, что это не может относиться к моей проблеме, но я также хотел бы применить это к полю имени)

Моя попытка решения

Я буду использовать запрос Bool / If, состоящий из трех запросов (соответствующих трем приоритетам выше), используя boost для определения относительной важности.

Проблема, с которой я столкнулся, связана с запросом префикса - он, похоже, не вмещает поисковый запрос в нижнем регистре, несмотря на то, что в моем поисковом анализаторе установлен фильтр нижнего регистра . Например, приведенный ниже запрос возвращает «Гарри Поттер» для «Гарри», но возвращает ноль результатов для «Гарри»:

{ "query": { "prefix": { "Name.raw" : "Harry" } } }

Я с помощью API _analyze подтвердил, что оба моих анализатора действительно переводят текст с «Гарри» на «Гарри». Куда я иду не так?

Из документации ES я понимаю, что нужно проанализировать поле Имя двумя различными способами, чтобы разрешить использование запросов префикса и термина:

  1. с помощью токенайзера "keyword" для включения запроса Prefix (я применил это к полю .raw)

  2. с использованием стандартного анализатора для включения Term (я применил это в поле Имя)

Я проверил дубликаты вопросов, таких как этот , но ответы не помогли

Мое сопоставление и настройки ниже

Отображение индекса ES

{
    "myIndex": {
        "mappings": {
            "pages": {
                "properties": {
                    "Id": {},
                    "Name": {
                        "type": "text",
                        "fields": {
                            "raw": {
                                "type": "text",
                                "analyzer": "keywordAnalyzer",
                                "search_analyzer": "pageSearchAnalyzer"
                            }
                        },
                    "analyzer": "pageSearchAnalyzer"
                    },
                    "Tokens": {}, // Other fields not important for this question
                }
            }
        }
    }
}

Настройки индекса ES

{
    "myIndex": {
        "settings": {
            "index": {
                "analysis": {
                    "filter": {
                        "ngram": {
                            "type": "edgeNGram",
                            "min_gram": "2",
                            "max_gram": "15"
                        }
                    },
                    "analyzer": {
                        "keywordAnalyzer": {
                            "filter": [
                                "trim",
                                "lowercase",
                                "asciifolding"
                            ],
                            "type": "custom",
                            "tokenizer": "keyword"
                        },
                        "pageSearchAnalyzer": {
                            "filter": [
                                "trim",
                                "lowercase",
                                "asciifolding"
                            ],
                            "type": "custom",
                            "tokenizer": "standard"
                        },
                        "pageIndexAnalyzer": {
                            "filter": [
                                "trim",
                                "lowercase",
                                "asciifolding",
                                "ngram"
                                ],
                            "type": "custom",
                            "tokenizer": "standard"
                        }
                    }
                },
                "number_of_replicas": "1",
                "uuid": "l2AXoENGRqafm42OSWWTAg",
                "version": {}
            }
        }
    }
}

1 Ответ

0 голосов
/ 16 мая 2018

Запросы префикса не анализируют поисковые термины, поэтому текст, который вы передаете в него, обходит все, что будет использоваться в качестве поискового анализатора (в вашем случае настроенный search_analyzer: pageSearchAnalyzer), и оценивает Harry как есть непосредственно против harry potter с пользовательской фильтрацией по ключевым словам, которая была результатом применения keywordAnalyzer во время индексации.

В вашем случае здесь вам нужно будет сделать одну из следующих вещей:

  1. Поскольку вы используете фильтр lowercase в поле, вы всегда можете использовать строчные термины в запросе префикса (при необходимости используйте нижний регистр на стороне приложения)
  2. Выполнить запрос match для edge_ngram -анализированного поля вместо prefix запроса, как описано в документах ES search_analyzer

Вот пример последнего:

1) Создать индексный анализатор без ngram и (рекомендуемый) стандартный анализатор поиска

PUT my_index
{
  "settings": {
    "index": {
      "analysis": {
        "filter": {
          "ngram": {
            "type": "edgeNGram",
            "min_gram": "2",
            "max_gram": "15"
          }
        },
        "analyzer": {
          "pageIndexAnalyzer": {
            "filter": [
              "trim",
              "lowercase",
              "asciifolding",
              "ngram"
            ],
            "type": "custom",
            "tokenizer": "keyword"
          }
        }
      }
    }
  },
  "mappings": {
    "pages": {
      "properties": {
        "name": {
          "type": "text",
          "fields": {
            "ngram": {
              "type": "text",
              "analyzer": "pageIndexAnalyzer",
              "search_analyzer": "standard"
            }
          }
        }
      }
    }
  }
}

2) Индексировать некоторые образцы документов

POST my_index/pages/_bulk
{"index":{}}
{"name":"Harry Potter"}
{"index":{}}
{"name":"Hermione Granger"}

3) Запустить запрос на совпадение с полем ngram

POST my_index/pages/_search
{
  "query": {
    "match": {
      "query": "Har",
      "operator": "and"
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...