ElasticSearch:如何按子聚合唯一键数量过滤聚合结果?
解决方案:按子聚合桶数量过滤父聚合结果
当然可以实现你的需求!你想要只保留那些拥有多个子聚合(model)的父聚合桶(make),完全忽略像SuperCar这种只有单一车型的品牌,这可以通过Elasticsearch的**bucket_selector聚合**结合子聚合的桶数量来实现。
方法一:使用_bucket_count直接获取子聚合桶数量(推荐,ES 7.11+支持)
这个方法直接统计每个品牌下model聚合的桶数量,然后过滤掉数量≤1的品牌:
{ "size": 0, "aggs": { "make": { "terms": { "field": "make", "size": 0 }, "aggs": { "model": { "terms": { "field": "model" } }, "filter_valid_makes": { "bucket_selector": { "buckets_path": { "modelBucketCount": "model._bucket_count" }, "script": "params.modelBucketCount > 1" } } } } } }
关键部分解释:
model._bucket_count:这是Elasticsearch提供的内置变量,用来获取当前make桶下model聚合的子桶数量(也就是该品牌的车型种类数)bucket_selector的脚本条件params.modelBucketCount > 1:只保留那些车型种类数大于1的品牌,这样SuperCar就会被直接过滤掉,最终结果只会包含Mercedes和Bmw。
方法二:使用cardinality统计唯一值数量(兼容旧版ES)
如果你的Elasticsearch版本低于7.11,不支持_bucket_count,可以用cardinality聚合先统计每个品牌下model字段的唯一值数量,再基于这个值过滤:
{ "size": 0, "aggs": { "make": { "terms": { "field": "make", "size": 0 }, "aggs": { "model": { "terms": { "field": "model" } }, "model_unique_count": { "cardinality": { "field": "model" } }, "filter_valid_makes": { "bucket_selector": { "buckets_path": { "modelCount": "model_unique_count" }, "script": "params.modelCount > 1" } } } } } }
关键部分解释:
model_unique_count:用cardinality聚合统计每个品牌下model字段的唯一值数量,结果和子聚合桶数量一致- 同样通过
bucket_selector过滤掉唯一值数量≤1的品牌,达到你想要的效果。
执行上述任意一个查询后,返回的聚合结果就只会包含Mercedes和Bmw的条目,SuperCar会被完全忽略,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Teimuraz
相关产品推荐
相关产品推荐

