2013-12-17 4 views
28

У меня есть большая база данных имен, в основном из Шотландии. В настоящее время мы создаем прототип для замены существующего программного обеспечения, которое выполняет поиск. Это все еще в производстве, и мы стремимся как можно более точно завершить наши результаты к текущим результатам одного и того же поиска.ElasticSearch - Поиск человеческих имен

Я надеялся, что кто-то может помочь мне, я вхожу в поиск в Elastic Search, запрос «Michael Heaney», я получаю некоторые дикие результаты. Текущий поиск возвращает две основные фамилии: «Heaney» и «Heavey» все с именем «Michael», я могу получить результаты «Heaney» в Elastic Search, но я не могу получить «Heavey» и ES также возвращает людей без фамилии «Майкл», однако я ценю, что это связано с тем, что он является частью нечеткого запроса. Я знаю, что это узкий прецедент, так как это только один поиск, но получение этого результата и знание того, как я могу его получить, помогут.

Спасибо.

Mapping

{ 
    "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 
      } 
     } 
    } 
    } 
}' 

Fuzzy

{ 
"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 
        } 
       } 
      } 
     ] 
    } 
    } 
} 

ответ

28

Во-первых, я воссоздал ваш Текущая конфигурация в Play: https://www.found.no/play/gist/867785a709b4869c5543

Если вы идете туда, переключиться на -Tab «Анализ», чтобы увидеть, как преображается текст:

Примечание, например, что Heaney заканчивает Разбивается на лексемы, как [hn, heanei] с search_analyzer и как [HN, heanei] с index_analyzer. Обратите внимание на разницу случаев для термина «метафон». Таким образом, это не соответствует.

fuzzy -query не выполняет анализ текста времени запроса. Таким образом, вы сравниваете Heavey с heanei. У этого есть Damerau-Levenshtein distance дольше, чем позволяют ваши параметры.

Что вы действительно хотите сделать, это использовать нечеткую функциональность match. Матч делает делает анализ текста времени запроса и имеет нечеткость -параметр.

Что касается fuzziness, это немного изменилось в Lucene 4. До этого он обычно указывался как поплавок. Теперь его нужно указать как допустимое расстояние. Выясните, что: https://github.com/elasticsearch/elasticsearch/pull/4332/files

Причина, по которой вы получаете людей без имени Michael, заключается в том, что вы делаете bool.should. Это имеет OR-семантику. Достаточно совпадения, но с учетом результатов лучше, чем больше соответствует.

Наконец, объединение всей этой фильтрации в один и тот же термин не обязательно является наилучшим подходом. Например, вы не можете знать и форсировать точное написание. Что вы должны учитывать, это использовать multi_field для обработки поля разными способами.

Here's an example you can play with, с командами завитка, чтобы воссоздать его ниже. Тем не менее, я бы пропустил использование стримера «портье». Я сохранил это, чтобы показать, как работает 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" 
            } 
           } 
          } 
         ] 
        } 
       } 
      ] 
     } 
    } 
} 
' 
+0

Спасибо, Алекс. Позвольте мне разобраться во всей этой информации, и я отчитаю. Ответ выглядит очень тщательно. – Nate

+0

Мы только что опубликовали статью о нечетком поиске, которая может также представлять интерес: https://www.found.no/foundation/fuzzy-search/ –

+0

Заметите это. Большое спасибо за вашу помощь, я многому научился. – Nate

Смежные вопросы