如何在Elasticsearch中统计符合条件的分组聚合结果数量?
问题:统计Elasticsearch中按key分组取最新非Delete事件的总量
我需要统计Elasticsearch索引内符合以下条件的事件总量:按key字段分组取每组最新的事件,排除type为Delete的事件后计数。对应的SQL等价查询如下:
SELECT COUNT(1) as volume FROM ( SELECT key , type , ROW_NUMBER() OVER( PARTITION BY key ORDER BY timestamp DESC ) AS instance FROM event ) A WHERE type != 'Delete' AND instance = 1
我尝试了以下Elasticsearch查询,能返回分组后的最新事件详情,但我只需要最终的计数结果,且已知count API不支持聚合,希望得到最高效的实现方法:
GET /index/_search { "size": 0, "aggs": { "group_by_key": { "terms": { "field": "key", "size": 1000000 }, "aggs": { "top_record_per_group": { "top_hits": { "sort": [ { "timestamp": { "order": "desc" } } ], "size": 1 } } } } }, "query": { "bool": { "must_not": [ { "term": { "type": "Delete" } } ] } } }
补充示例
| key | type | timestamp | latest? | include? |
|---|---|---|---|---|
| 1 | insert | 00:00:01 | ||
| 1 | update | 00:00:02 | ||
| 2 | insert | 00:00:03 | ||
| 3 | insert | 00:00:04 | Y | Y |
| 2 | delete | 00:00:05 | Y | N |
| 4 | insert | 00:00:06 | ||
| 1 | update | 00:00:07 | Y | Y |
| 4 | update | 00:00:08 | Y | Y |
最终预期结果:volume: 3
高效实现方案
通过管道聚合可以在现有分组聚合的基础上,直接统计符合条件的分组数量,无需返回事件详情。修改后的查询如下:
GET /index/_search { "size": 0, "aggs": { "group_by_key": { "terms": { "field": "key", "size": 1000000 }, "aggs": { "top_record_per_group": { "top_hits": { "sort": [ { "timestamp": { "order": "desc" } } ], "size": 1, "_source": ["type"] // 只返回type字段,减少数据传输开销 } }, // 筛选出top_hits中type不为Delete的分组 "filter_valid_type": { "bucket_selector": { "buckets_path": { "type": "top_record_per_group.hits.hits.0._source.type" }, "script": "params.type != 'Delete'" } } } }, // 统计经过筛选后的分组数量,即最终volume "total_volume": { "bucket_count": { "buckets_path": "group_by_key>filter_valid_type" } } } }
说明
filter_valid_type聚合通过bucket_selector脚本判断每组最新事件的type是否不为Delete,只保留符合条件的分组total_volume聚合通过bucket_count统计筛选后的分组数量,结果直接返回在aggregations.total_volume.value字段中- 优化点:在
top_hits中指定_source: ["type"],只返回需要的字段,减少数据传输开销
如果你的数据量极大(超过千万级key),terms聚合的size参数可能受限于Elasticsearch的index.max_result_window设置,此时可以改用composite聚合进行分页式分组,再结合管道聚合统计总数,但对于大部分场景,上述方案已足够高效。
内容的提问来源于stack exchange,提问作者AlanTwoRings
相关产品推荐
相关产品推荐

