如何对聚合计数值做范围聚合以统计不同文档量区间的userId数量
实现思路
要完成跨聚合输出值的范围统计,核心是搭建两阶段嵌套聚合链路,不需要额外拉取数据到本地计算:
- 第一阶段:先按
userId做分桶统计,拿到每个用户名下的文档总数量 - 第二阶段:直接调用原生的管道聚合能力,对第一阶段输出的每个用户的文档计数值做范围划分,最终统计每个区间内的用户总数
可直接复用的聚合查询
针对你给出的文档结构(包含path、userId字段),可以直接使用如下DSL完成统计:
{ "size": 0, "aggs": { // 第一阶段:逐用户统计文档数 "per_user_doc_stat": { "terms": { "field": "userId.keyword", // 必须根据实际的不重复userId总量调整size,默认仅返回前10个分桶会导致结果漏算 "size": 20000 } }, // 第二阶段:对上游输出的每个用户的文档数做范围分桶 "user_count_by_docs_range": { "range_bucket": { // 指定取上游每个用户分桶的内置计数值(即该用户的文档总量)作为统计源 "buckets_path": "per_user_doc_stat>_count", "ranges": [ { "from": 100, "key": "超过100篇文档" }, { "from": 50, "to": 100, "key": "50至100篇文档" }, { "to": 100, "key": "不足100篇文档" } ] } } } }
查询返回的每个范围分桶的doc_count值,就是对应区间内的userId总数量。
常见注意事项
- 如果你的
userId字段在索引映射中是普通文本类型,聚合时必须指定对应的keyword子字段(即userId.keyword),否则会触发类型错误,或得到精度不足的聚合结果 - 必须根据实际的userId总量调整第一阶段terms聚合的
size参数,默认值仅返回前10个分桶,会遗漏大量用户导致统计结果失准。如果userId总量较大、超过普通terms聚合的单批拉取上限,可以替换为composite聚合作为第一阶段的分桶手段,分批遍历所有用户的文档数,避免单次查询占用过多内存 - 上述用到的
range_bucket是原生提供的管道聚合能力,专门用于对上游聚合的输出计数值做范围划分,不需要自行编写脚本转换数据 - 注意区间边界设置:如果需要三个完全不重叠的统计分类,需要把“不足100篇文档”的区间调整为“不足50篇文档”,否则50-100区间的用户会同时被统计到“不足100篇文档”的分类里,出现计数交叉
内容的提问来源于stack exchange,提问作者user2478384
相关产品推荐
相关产品推荐

