Elasticsearch如何实现带过滤的平均值聚合?
实现带过滤条件的平均值聚合需求
针对你提出的两种场景,我们可以通过Elasticsearch的聚合API分别处理,核心思路是给length的平均值聚合添加过滤条件,同时保持width的平均值聚合计算所有文档:
场景1:排除length=100的文档
我们可以使用FilterAggregation包裹length的平均值聚合,先筛选出length != 100的文档,再计算这部分文档的length平均值;width的平均值聚合直接保留原逻辑,计算所有文档的平均值。
修改后的代码如下:
termAggregation.subAggregation( AggregationBuilders.filter("filtered_length_avg", QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("length", 100)) ).subAggregation(AggregationBuilders.avg("length_avg").field("length")) ).subAggregation(AggregationBuilders.avg("width_avg").field("width"));
- 外层
filter聚合会先过滤掉length等于100的文档,再在剩余文档上计算length平均值,结果为预期的9 width的平均值聚合不受过滤影响,计算所有3个文档的平均值,结果为预期的5
场景2:排除不存在length字段的文档
当部分文档没有length字段时,我们需要筛选出包含length字段的文档来计算平均值,同样用FilterAggregation结合exists查询实现:
修改后的代码如下:
termAggregation.subAggregation( AggregationBuilders.filter("filtered_length_avg", QueryBuilders.existsQuery("length") ).subAggregation(AggregationBuilders.avg("length_avg").field("length")) ).subAggregation(AggregationBuilders.avg("width_avg").field("width"));
existsQuery("length")会筛选出带有length字段的文档,仅对这些文档计算length平均值width的平均值聚合依然计算所有文档的平均值,结果为(8+2+5)/3=5
结果获取示例
聚合执行后,可通过以下方式提取结果:
// 获取过滤后的length平均值 Filter filteredLengthAvg = searchResponse.getAggregations().get("filtered_length_avg"); Avg lengthAvg = filteredLengthAvg.getAggregations().get("length_avg"); double lengthAvgValue = lengthAvg.getValue(); // 获取width的全局平均值 Avg widthAvg = searchResponse.getAggregations().get("width_avg"); double widthAvgValue = widthAvg.getValue();
内容的提问来源于stack exchange,提问作者Milo
相关产品推荐
相关产品推荐

