如何在Elasticsearch中利用聚合值计算平均值并实现多操作查询
Elasticsearch 单查询实现过滤、分组计数及特定响应码平均值计算
没问题,我来帮你搞定这个Elasticsearch的查询需求!咱们一步一步来实现你要的所有功能,用单个查询就能完成所有要求。
首先,先给你完整的查询示例,之后我会拆解每个部分的作用:
{ "size": 0, // 不需要返回原始文档,只关注聚合结果 "query": { "bool": { "filter": [ { "range": { "createdDate": { "gte": "2019-10-31T00:00:00.000Z", "lte": "2019-10-31T23:59:59.999Z" } } }, { "terms": { "responseCode": ["200", "300", "400"] // 替换成你要过滤的响应码集合 } }, { "terms": { "metricName": ["call", "email", "chat"] // 替换成你要过滤的指标名称集合 } } ] } }, "aggs": { "group_by_createdDate": { "terms": { "field": "createdDate", "format": "yyyy-MM-dd'T'HH:mm:ss.SSSZ" }, "aggs": { "group_by_metricName": { "terms": { "field": "metricName" }, "aggs": { "total_records": { "value_count": { "field": "_id" // 统计每个(日期+指标)分组的总记录数 } }, "specific_code_record_count": { "filter": { "term": { "responseCode": "200" // 替换成你要统计的特定响应码 } }, "aggs": { "count": { "value_count": { "field": "_id" } } } } } }, "avg_specific_code_records": { "avg_bucket": { "buckets_path": "group_by_metricName>specific_code_record_count>count" } } } } } }
各部分功能拆解
1. 过滤数据(需求1)
我用了bool.filter来组合多个过滤条件,这种方式不会影响文档的评分,纯粹做数据筛选:
range查询:精确匹配createdDate的时间范围,你可以根据需要调整gte和lte的值;terms查询:匹配你指定的responseCode和metricName集合,如果只需要单个值,把terms换成term即可。
2. 分组与统计数量(需求2、3)
通过两层terms聚合实现分组,再用value_count统计数量:
- 第一层
group_by_createdDate:按createdDate对数据分组; - 第二层
group_by_metricName:在每个日期分组内,再按metricName细分分组; total_records:用value_count统计每个(日期+指标)分组的总记录数,完全满足你要的“获取每个分组的记录数量”需求。
3. 计算特定响应码的平均值(需求4)
这里用了嵌套聚合+avg_bucket来实现:
- 首先在每个(日期+指标)分组内,用
filter聚合筛选出你关注的特定响应码(比如示例中的200),再统计这些记录的数量; - 然后在日期分组下,用
avg_bucket聚合遍历该日期下所有指标分组的特定响应码记录数,自动计算出平均值,这就是你要的“同一createdDate下包含特定responseCode的记录的平均值”。
扩展:基于聚合值计算其他平均值
如果你的需求是计算其他类型的平均值(比如特定响应码记录数占分组总记录数的比例的平均值),可以用bucket_script先计算单个分组的比例,再用avg_bucket求平均。比如:
在group_by_metricName的聚合里添加:
"specific_code_ratio": { "bucket_script": { "buckets_path": { "specificCount": "specific_code_record_count>count", "totalCount": "total_records" }, "script": "params.specificCount / params.totalCount" } }
然后在group_by_createdDate下添加:
"avg_specific_code_ratio": { "avg_bucket": { "buckets_path": "group_by_metricName>specific_code_ratio" } }
这样就能得到同一日期下,各指标分组中特定响应码记录占比的平均值了。
内容的提问来源于stack exchange,提问作者Prince Leo
相关产品推荐
相关产品推荐

