Elasticsearch不同版本使用nGram分词时模糊匹配结果不一致问题
问题根因
这个差异是Elasticsearch 7.0版本引入的两项查询逻辑变更共同导致的:
- fuzziness作用范围变更
ES 6.8及更早版本中,multi_match查询的fuzziness参数会作用于查询分词后的每一个独立term,只要每个查询term能通过精确或模糊匹配命中目标文档的任意一个倒排索引term,就满足operator: AND的要求。对应你的场景:
查询词acinash分词得到aci、cin、ina、nas、ash5个term,其中aci编辑距离1匹配avi,cin编辑距离1匹配vin,剩下3个term精确匹配,所有term都命中,因此返回文档。
ES 7.0之后,multi_match的best_fields类型默认会将模糊匹配的校验粒度从「单个分词term」升级为「整个查询分词序列」,要求模糊匹配的term在文档分词序列中的相对位置和查询分词序列完全一致,同时你设置了slop: 0不允许term位置偏移,进一步限制了匹配可能。 - 模糊候选集生成逻辑优化
ES 7.0为了降低模糊查询的性能开销,修改了模糊候选term的生成规则:当max_expansions设置为50时,系统会优先返回索引中频率最高的前N个候选term,你的场景中aci的模糊候选avi如果在索引中的频率低于其他候选,就会被排除在匹配列表之外,导致aci无法命中,最终operator: AND校验失败。
修复方案
你可以通过以下任意一种方式恢复6.8的匹配效果:
- 将
multi_match的type从best_fields改为most_fields,关闭序列位置校验 - 适当调大
max_expansions参数值(比如调整到200),保证目标候选term不会被过滤 - 去掉
operator: AND配置,改用minimum_should_match设置匹配比例(比如"minimum_should_match": "80%"),允许少量term不匹配
内容的提问来源于stack exchange,提问作者Akash Gupta
相关产品推荐
相关产品推荐

