Запрос в ElasticSearch, чтобы соответствовать части слова - PullRequest
0 голосов
/ 23 мая 2018

Я пытаюсь написать запрос в ElasticSearch, который сопоставляет непрерывные символы в словах.Итак, если в моем индексе есть «Джон Доу», я все равно должен увидеть «Джон Доу», возвращенный Elasticsearch для следующих поисков.

  1. Джон Доу
  2. Джон До
  3. ohn do
  4. john
  5. n doe

До сих пор я пробовал следующий запрос.

{
  "query": {
    "multi_match": {
      "query": "term",
      "operator": "OR",
      "type": "phrase_prefix",
      "max_expansions": 50,
      "fields": [
        "Field1",
        "Field2"
      ]
    }
  }
}

Но это также возвращаетнеестественные совпадения, как будто я все еще получу «Джон Доу», когда я наберу Джон Х.

Ответы [ 2 ]

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

Как объяснено в моем комментарии выше, следует избегать подстановочных знаков префиксов любой ценой по мере роста индекса, поскольку это заставит ES выполнять полное сканирование индекса.Я до сих пор убежден, что ngrams (точнее, edge-ngrams) - это путь, поэтому я делаю удар ниже:

Идея состоит в том, чтобы проиндексировать все суффиксы ввода, а затемиспользуйте prefix запрос для сопоставления с любым суффиксом, поскольку при поиске префиксов не возникают те же проблемы с производительностью, что и при поиске суффиксов.Таким образом, идея состоит в том, чтобы индексировать john doe следующим образом:

john doe
ohn doe
hn doe
n doe
doe
oe
e

Таким образом, используя запрос prefix, мы можем сопоставить любую часть этих токенов, которая эффективно достигает цели сопоставления частично смежных словв то же время обеспечивая хорошую производительность.

Определение индекса будет выглядеть следующим образом:

PUT my_index
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_analyzer": {
            "type": "custom",
            "tokenizer": "keyword",
            "filter": [
              "lowercase",
              "reverse",
              "suffixes",
              "reverse"
            ]
          }
        },
        "filter": {
          "suffixes": {
            "type": "edgeNGram",
            "min_gram": 1,
            "max_gram": 20
          }
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "type": "text",
          "analyzer": "my_analyzer",
          "search_analyzer": "standard"
        }
      }
    }
  }
}

Тогда мы можем проиндексировать образец документа:

PUT my_index/doc/1
{
  "name": "john doe"
}
* 1018И, наконец, все последующие поиски вернут документ john doe:
POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john doe"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john do"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "ohn do"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "john"
    }
  }
}

POST my_index/_search 
{
  "query": {
    "prefix": {
      "name": "n doe"
    }
  }
}
0 голосов
/ 29 мая 2018

Вот что у меня сработало.Вместо ngram, индексируйте свои данные как ключевое слово.И используйте совпадение с регулярным выражением, чтобы соответствовать словам.

 "query": {
          "bool": {
              "should": [
                {
                  "wildcard": { "Field1": "*" + term + "*" }
                },
                {
                  "wildcard": { "Field2": "*" + term + "*" }
                }
              ],
              "minimum_should_match": 1
          }
      }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...