2013-12-17 48 views
28

我有一個大型的名字數據庫,主要來自蘇格蘭。我們目前正在生產一個原型來取代現有的一個搜索軟件。這仍在製作中,我們的目標是讓我們的結果儘可能地接近當前搜索的結果。ElasticSearch - 尋找人名

我希望有人能幫助我,我進入一個搜索彈性搜索,查詢是「邁克爾Heaney」,我得到了一些野生的結果。目前的搜索返回兩個主要的姓氏,這些是 - 「Heaney」和「Heavey」都帶有「Michael」的名字,我可以在Elastic Search中獲得「Heaney」結果,但是我無法獲得「Heavey」,ES也返回沒有姓氏「邁克爾」的人,但我明白,這是由於它是模糊查詢的一部分。我知道這是一個狹義的用例,因爲它只有一個搜索,但得到這個結果並知道我可以如何獲得它會有所幫助。

謝謝。

映射

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

回答

28

首先,我重新創建你的https://www.found.no/play/gist/867785a709b4869c5543

如果你去那裏,切換到「分析」 -Tab看文字是如何轉化:在播放當前配置

注意,例如該Heaney結束了切分作爲[hn, heanei]search_analyzer和如[HN, heanei]index_analyzer。注意metaphone-term的情況差異。因此,那個不匹配。

fuzzy -query不執行查詢時間文本分析。因此,您最終將Heaveyheanei進行比較。這有一個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,用curl命令在下面重新創建它。但是,我完全不用這個「porter」stemmer。我只是爲了展示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