2014-04-23 169 views
5

我正在使用ElasticSearch構建自動完成功能。當用戶鍵入時,我想顯示數據中的完成列表,以便用戶選擇一個。例如,如果數據包含以下短語:ElasticSearch短語前綴搜索 - 如何獲得匹配的短語?

very unusual 
very unlikely 
very useful 

和用戶類型:

very u 

我想顯示上述的短語。

我使用這個查詢:

"query": { 
    "multi_match": { 
     "query": "very u", 
     "fields": [ 
     "name", 
     "description", 
     "contentBlocks.caption", 
     "contentBlocks.text" 
     ], 
     "type": "phrase_prefix", 
     "max_expansions": 10, 
     "cutoff_frequency": 0.001 
    } 

這是我要尋找的內容相匹配,但是從搜索結果中提取匹配的短語是相當尷尬的。我一直在使用突出顯示,並通過解析亮點來收集匹配的短語。例如:

"highlight": { 
     "contentBlocks.text": [ 
     "turned the <em>very</em> <em>unusual</em> doorknob" 
     ] 
    } 

    "highlight": { 
     "contentBlocks.text": [ 
     "invented a <em>very</em> <em>useful</em> mechanism" 
     ] 
    } 

什麼是正確的方法來做到這一點?


「短語提示」可能能夠完成我所描述的內容,但是如何才能做到這一點並不明顯。

我已經索引感興趣的領域(例如,「說明」)如下:

"description" : { 
    "index_analyzer" : "snowball_stem", 
    "search_analyzer" : "snowball_stem", 
    "type" : "string", 
    "fields" : { 
     "autocomplete" : { 
     "index_analyzer" : "shingle_analyzer", 
     "search_analyzer" : "shingle_analyzer", 
     "type" : "string" 
     } 
    } 
    }, 

我現在用的是snowball_stem分析儀搜索,並自動完成功能的shingle_analyzer。 shingle_analyzer看起來是這樣的:

"settings" : { 
    "analysis" : { 
     "analyzer" : { 
      "shingle_analyzer" : { 
       "type" : "custom", 
       "tokenizer" : "standard", 
       "filter" : [ 
        "standard", 
        "lowercase", 
        "shingle_filter" 
       ], 
       "char_filter" : [ 
        "html_strip" 
       ] 
      } 
     }, 
     "filter" : { 
      "shingle_filter" : { 
       "type" : "shingle", 
       "min_shingle_size" : 2, 
       "max_shingle_size" : 2 
      } 
     } 
    } 
}, 

的短語建議者的文件似乎向「拼寫糾錯」,而不是完成完全被導向。自從我後是完成,我設置了直接生成的min_word_length和的prefix_length到輸入文本的長度,在這種情況下,2

我製作了一個建議查詢基於文檔:

{ 
    "text" : "sa", 
    "autocomplete_description" : { 
     "phrase" : { 
      "analyzer" : "standard", 
      "field" : "description.autocomplete", 
      "size" : 10, 
      "max_errors" : 2, 
      "confidence" : 0.0, 
      "gram_size" : 2, 
      "direct_generator" : [ 
       { 
        "field" : "description.autocomplete", 
        "suggest_mode" : "always", 
        "size" : 10, 
        "min_word_length" : 2, 
        "prefix_length" : 2 
       } 
      ] 
     } 
    } 
} 

該搜索爲「sa」的建議,結果如下出現:

{ 
    "_shards" : { 
    "total" : 1, 
    "successful" : 1, 
    "failed" : 0 
    }, 
    "autocomplete_description" : [ { 
    "text" : "sa", 
    "offset" : 0, 
    "length" : 2, 
    "options" : [ { 
     "text" : "say", 
     "score" : 0.012580795 
    }, { 
     "text" : "sa", 
     "score" : 0.01127677 
    }, { 
     "text" : "san", 
     "score" : 0.0106529845 
    }, { 
     "text" : "sad", 
     "score" : 0.008533429 
    }, { 
     "text" : "saw", 
     "score" : 0.008107899 
    }, { 
     "text" : "sam", 
     "score" : 0.007155634 
    } ] 
    } ] 
} 

我希望找到的輸入「SA」是任何長度的「SA」開頭的單詞。爲什麼它只返回兩個或三個字符的單詞?爲什麼它只返回六個選項?我一直使用的multi_match phrase_prefix查詢會查找以「sa」開頭的許多較長的單詞,如「save」,「sassy」,「safari」和「salad」。

當我搜索多詞文本的建議時,如「one or」(在數據中出現很多次),它什麼也找不到。 multi_match phrase_prefix查詢找到「一個或多個」,「一個或者」,「一個或者你」和「一個或者兩個」。

我怎樣才能讓這個建議者做我想做的事?

+0

如果您有任何問題,請告訴我,或者我可以在我的答案中添加任何內容。 –

+0

我來看看。 –

+0

我嘗試過使用短語提示器來做到這一點,但我沒有取得太大的成功。我在上面的問題描述中添加了關於我的實驗的信息和更詳細的問題。 –

回答

1

你可以用completion suggester粗略地得到你想要的。這個問題的主要問題是它不再是搜索意識。您可以通過添加suggester context來解決此問題,但它僅適用於過濾器,並且不會考慮搜索文本。

,我知道,以獲得「最佳」的行爲(情境感知搜索的完成)的唯一方法是做到以下幾點:

  • 創建suggestions場,其中文本標記化,你會希望它可以被用戶看到(可能是標準分析器或者可能添加2格令牌過濾器)。
  • 比方說,用戶發出不完整的查詢very un。在幕後發佈搜索very,然後使用term aggregations獲取與搜索上下文匹配的列表字詞,但限制使用"include": "un.*"返回的字詞。
  • 生成的列表看起來像[異常,不太可能,不酷]。

用這種方法,尤其是在分片環境中唯一的問題是,這是一個很大的查詢和你拉一個非常高的基數場(suggestions)到內存中。所以......我不知道這是否可行。所以也許最好回到完成建議者身邊。如果你嘗試這些,我很樂意聽到你的經驗。

+1

感謝您關注此事,@JnBrymn。我最終使用了我最初描述的代碼,使用phrase_prefix查詢並對亮點進行後處理。它看起來像一個黑客,但它的工作可靠,性能出奇地好。 –