2014-04-23 167 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查询并对亮点进行后处理。它看起来像一个黑客,但它的工作可靠,性能出奇地好。 –