Elasticsearch中term查询无结果但match查询可匹配是什么原因?
核心原因
这个问题的本质是term查询的匹配逻辑和metric_name字段的分词策略不匹配,这是ES检索的常见误区:
- term查询的「精确匹配」指的是和倒排索引中存储的分词后生成的词条做完全一致的匹配,不是和文档写入的原始字段值匹配。
- match查询会先对你输入的查询字符串,使用和
metric_name字段相同的分词器做分词处理,再用生成的词条去倒排索引匹配,因此可以正常命中结果。
你的场景具体问题
大概率是metric_name字段使用了ES默认的text类型,配套的standard标准分词器会对写入的字符串做强制小写转换处理:
你写入的原始值ConsumedReadCapacityUnits被分词后生成的词条是全小写的consumedreadcapacityunits,你用term查询传入大写开头的原始值,自然无法匹配到倒排索引中的小写词条。而match查询会把你传入的查询字符串也转成小写,因此可以正常命中。
还有一种常见情况是你配置的分词器对驼峰命名的字符串做了拆分,把ConsumedReadCapacityUnits拆成了consumed、read、capacity、units多个词条,term查询传入完整字符串自然无法匹配。
解决方案
方案1:使用keyword子字段精确匹配(推荐,不需要改mapping)
ES默认会给所有text类型字段加一个keyword类型的子字段,该字段不会做任何分词、转换,直接存储原始值,直接用term查询该子字段即可:
POST/_search { "query": { "term":{ "metric_name.keyword" : {"value": "ConsumedReadCapacityUnits","boost": 1.0} } } }
方案2:修改字段mapping为keyword类型
如果metric_name字段本身就是用于精确匹配的枚举类字段,不需要分词检索,直接修改mapping将字段类型设为keyword,后续新写入的数据就可以直接用term查询原始值命中。
方案3:匹配分词后的词条(不推荐)
如果确实需要查询text类型字段的词条,将term查询的传入值修改为和分词结果完全一致的内容即可,比如本例中传入全小写的consumedreadcapacityunits,但该方式维护成本高,不建议生产使用。
内容的提问来源于stack exchange,提问作者Joey Yi Zhao
相关产品推荐
相关产品推荐

