ElasticSearch-Поиск Человеческих Имен
У меня есть большая база имен, в основном из Шотландии. В настоящее время мы производим прототип для замены существующего программного обеспечения, которое выполняет поиск. Это все еще находится в производстве, и мы стремимся получить наши результаты как можно ближе к текущим результатам того же поиска.
Я надеялся, что кто-то может мне помочь, я ввожу поиск в Elastic Search, запрос "Michael Heaney", я получаю некоторые дикие результаты. Текущий поиск возвращает два основных фамилии, это - "Heaney" и "Heavey" все с именем "Michael", я могу получить результаты" Heaney "в эластичном поиске, однако я не могу получить" Heavey", и ES также возвращает людей без фамилии" Michael", однако я ценю, что это связано с тем, что это часть нечеткого запроса. Я знаю, что это узкий вариант использования, так как это только один поиск, но получение этого результата и знание того, как я могу его получить, поможет.
Спасибо.
Отображение
{
"jr": {
"_all": {
"enabled": true,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer"
},
"properties": {
"pty_forename": {
"type": "string",
"index": "analyzed",
"boost": 2,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
},
"pty_full_name": {
"type": "string",
"index": "analyzed",
"boost": 4,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
},
"pty_surname": {
"type": "string",
"index": "analyzed",
"boost": 4,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
}
}
}
}'
Индекс Настройки
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"index_analyzer": {
"tokenizer": "standard",
"filter": [
"standard",
"my_delimiter",
"lowercase",
"stop",
"asciifolding",
"porter_stem",
"my_metaphone"
]
},
"search_analyzer": {
"tokenizer": "standard",
"filter": [
"standard",
"my_metaphone",
"synonym",
"lowercase",
"stop",
"asciifolding",
"porter_stem"
]
}
},
"filter": {
"synonym": {
"type": "synonym",
"synonyms_path": "synonyms/synonyms.txt"
},
"my_delimiter": {
"type": "word_delimiter",
"generate_word_parts": true,
"catenate_words": false,
"catenate_numbers": false,
"catenate_all": false,
"split_on_case_change": false,
"preserve_original": false,
"split_on_numerics": false,
"stem_english_possessive": false
},
"my_metaphone": {
"type": "phonetic",
"encoder": "metaphone",
"replace": false
}
}
}
}
}'
Нечеткий
{
"from":0, "size":100,
"query": {
"bool": {
"should": [
{
"fuzzy": {
"pty_surname": {
"min_similarity": 0.2,
"value": "Heaney",
"prefix_length": 0,
"boost": 5
}
}
},
{
"fuzzy": {
"pty_forename": {
"min_similarity": 1,
"value": "Michael",
"prefix_length": 0,
"boost": 1
}
}
}
]
}
}
}
1 ответ:
Во-первых, я воссоздал вашу текущую конфигурацию в игре: https://www.found.no/play/gist/867785a709b4869c5543
Если вы перейдете туда, перейдите на вкладку "Анализ", чтобы увидеть, как преобразуется текст:
Обратите внимание, например, чтоHeaney
в конечном итоге маркируется как[hn, heanei]
сsearch_analyzer
и как[HN, heanei]
сindex_analyzer
. Примечание в случае-разница для метафон-термин. Таким образом, это одно не соответствует.То, что вы действительно хотите сделать, - это использовать нечеткую функциональность
fuzzy
-запрос не выполняет анализ текста во время запроса. Таким образом, вы заканчиваете вверх по сравнениюHeavey
сheanei
. Это расстояниеДамерау-Левенштейна больше, чем позволяют ваши параметры.match
. Match делает анализ текста во время запроса и имеет нечеткость-параметр.Что касается
Причина, по которой вы получаете людей без имениfuzziness
, это немного изменилось в Lucene 4. Раньше это были, как правило, указан в качестве поплавка. Теперь это должно быть указано как допустимое расстояние. Есть выдающаяся тяга просьба разъяснить, что: https://github.com/elasticsearch/elasticsearch/pull/4332/filesMichael
, заключается в том, что вы делаетеbool.should
. Это или-семантика. Достаточно того, что один соответствует, но забивать-это лучше, чем больше это соответствует. Наконец, объединение всей этой фильтрации в один и тот же термин не обязательно является лучшим подходом. Например, вы не можете знать и усиливать точное написание. Что вы должны делать рассмотрим использованиеmulti_field для обработки поля многими способами.Вот пример, который вы можете воспроизвести с , с командами curl, чтобы воссоздать его ниже. Однако я бы полностью отказался от использования штеммера "Портер" для этого. Я сохранил его только для того, чтобы показать, как работает multi_field. Использование сочетания матч, матч с нечеткостью и фонетическое соответствие должно привести вас далеко. (Убедитесь, что вы не допускаете нечеткости, когда делаете фонетическое сопоставление - или вы получите бесполезное нечеткое сопоставление. :- )
#!/bin/bash export ELASTICSEARCH_ENDPOINT="http://localhost:9200" # Create indexes curl -XPUT "$ELASTICSEARCH_ENDPOINT/play" -d '{ "settings": { "analysis": { "text": [ "Michael", "Heaney", "Heavey" ], "analyzer": { "metaphone": { "type": "custom", "tokenizer": "standard", "filter": [ "my_metaphone" ] }, "porter": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "porter_stem" ] } }, "filter": { "my_metaphone": { "encoder": "metaphone", "replace": false, "type": "phonetic" } } } }, "mappings": { "jr": { "properties": { "pty_surename": { "type": "multi_field", "fields": { "pty_surename": { "type": "string", "analyzer": "simple" }, "metaphone": { "type": "string", "analyzer": "metaphone" }, "porter": { "type": "string", "analyzer": "porter" } } } } } } }' # Index documents curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d ' {"index":{"_index":"play","_type":"jr"}} {"pty_surname":"Heaney"} {"index":{"_index":"play","_type":"jr"}} {"pty_surname":"Heavey"} ' # Do searches curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d ' { "query": { "bool": { "should": [ { "bool": { "should": [ { "match": { "pty_surname": { "query": "heavey" } } }, { "match": { "pty_surname": { "query": "heavey", "fuzziness": 1 } } }, { "match": { "pty_surename.metaphone": { "query": "heavey" } } }, { "match": { "pty_surename.porter": { "query": "heavey" } } } ] } } ] } } } '