Elasticsearch无法基于shingles字段正确过滤聚合结果
问题根因
当前写法中的wildcard过滤属于文档级过滤:只要单条文档的name.shingles字段存在任意一个匹配*red*规则的分词,整条文档就会被划入聚合统计范围。
内层的terms聚合是对范围内所有文档的name.shingles字段的全部分词做计数统计,不会对单个分词桶做规则校验。实际返回中出现的aces of、aces of the这类不符合规则的key,本质是因为那些匹配了外层过滤规则的文档,本身除了携带turning red这类符合要求的shingle分词,还同时携带了其他无关分词,这些无关分词会被terms聚合正常统计计数,最终出现在返回的桶列表里。
修复方案
给terms聚合增加include参数做桶级过滤即可,该参数支持正则匹配,只会返回符合规则的聚合桶,修改后的查询结构如下:
"aggregations": { "test": { "filter": { "wildcard": { "name.shingles": { "value": "*red*" } } }, "aggs": { "shingles": { "terms": { "field": "name.shingles", "size": 3, "include": ".*red.*" } } } } }
注意include使用正则语法,因此用.*red.*对应wildcard规则里的*red*匹配效果。
- 如果你只需要统计全量索引中所有带
red的shingle分词计数,不需要先筛选出含red的文档,可以直接去掉外层的filter聚合,仅靠terms的include规则就能实现,查询性能更高。 - 如果你需要先筛选出含red内容的文档,再统计这批文档里所有带red的shingle项,保留外层filter再加
include参数的写法即可满足需求。
内容的提问来源于stack exchange,提问作者user18154574
相关产品推荐
相关产品推荐

