有没有办法让ElasticSearch识别分析字段的完全匹配?理想情况下,我想小写,标记,干,甚至语音化我的文档,然后让查询拉出“精确”匹配 .
我的意思是,如果我将“汉堡包”和“汉堡包”编入索引,它们将被分析为[“汉堡包”,“包子”]和[“汉堡包”] . 如果我搜索“汉堡包”,它将仅返回“汉堡包”文档,因为这是“精确”匹配 .
我尝试过使用关键字tokenizer,但这不会阻止个别令牌 . 我是否需要做一些事情以确保令牌的数量相等?
我熟悉多字段并使用“not_analyzed”类型,但这比我正在寻找的更具限制性 . 我想要完全匹配,后期分析 .
3 回答
使用带状疱疹标记器以及阻塞和其他任何需要的东西 . 添加
token_count
类型的子字段,该字段将计算字段中的标记数 .在搜索时,您需要添加一个额外的过滤器,以使索引中的标记数与搜索文本中的标记数相匹配 . 在执行实际搜索时,您需要一个额外的步骤来计算搜索字符串中的标记 . 这是这样的,因为带状符会创建令牌的多个排列,您需要确保它与搜索文本的大小相匹配 .
尝试这个,只是为了给你一个想法:
和查询:
shingles
过滤器在这里很重要,因为它可以创建令牌组合 . 更重要的是,这些是保持订单或令牌的组合 . Imo,这里最难实现的要求是更改标记(词干,小写等),并且还要回收原始文本 . 除非您定义自己的"concatenation"过滤器,否则我认为除了使用shingles
过滤器之外没有其他任何方法 .但是对于
shingles
,还有另一个问题:它创建了不需要的组合 . 对于像"Hamburgers buns in Los Angeles"
这样的文本,你会得到一长串的带状疱疹:如果您只对那些符合 exactly 含义的文档感兴趣,则上述文档仅在您搜索"hamburgers buns in los angeles"时匹配(并且与"any hamburgers buns in los angeles"不匹配),那么您需要一种方法来过滤那长长的带状疱疹列表 . 我看到的方式是使用
word_count
.您可以将分析器保持为您的预期(小写,标记,词干......),并使用
query_string
作为主查询,match_phrase
作为搜索的提升查询 . 像这样的东西:它将匹配两个文档,并且完全匹配(match_phrase)将位于顶部,因为查询匹配
should
子句(并获得更高的分数)default_operator
设置为OR,它将帮助查询"Hamburger Buns"(匹配hamburger
或bun
)也匹配文档"Hamburger" .phrase_slop
设置为1以匹配距离= 1的项,例如搜索Hamburger Buns
将与文档Hamburger Big Buns
不匹配 . 您可以根据您的要求进行调整 .您可以参考Closer is better,Query string了解更多详情 .
您可以为此目的使用multi-fields并在
analyzed
字段中有一个not_analyzed
子字段(在本例中我们称之为item
) . 您的映射必须如下所示:通过这种映射,您可以检查分析器相对于多字段
item
和item.raw
的每个值Hamburgers
和Hamburger Buns
是如何"viewed"对于
Hamburger
:对于
Hamburger Buns
:正如您所看到的,
not_analyzed
字段将完全按照输入的方式进行索引 .现在,让我们索引两个示例文档来说明这一点:
最后,为了回答你的问题,如果你想在
Hamburger
上进行完全匹配,你可以在你的子字段item.raw
中搜索(注意案例也必须匹配):你会得到:
UPDATE (see comments/discussion below and question re-edit)
从评论中获取您的示例并尝试使
HaMbUrGeR BuNs
匹配Hamburger buns
您可以使用match
这样的查询来实现它 .基于上述相同的两个索引文档将产生