Elasticsearch按website字段分组并对数值求和的实现方法
需求可行性结论
该需求完全可以实现,不需要拉取全量数据到业务侧计算,直接通过Elasticsearch原生的聚合能力就能完成,性能远高于拉取原始记录后手动统计的方案。
实现逻辑说明
核心是两类聚合搭配使用:
- 用
terms桶聚合,按网站字段做维度拆分,每个网站对应一个独立的数据桶 - 在每个网站桶内部嵌套
sum指标聚合,对桶内所有记录的目标数值字段做累加求和
具体操作步骤
- 提前确认字段映射合规
- 分组用的网站字段
site.website需为keyword类型,如果是text类型的分词字段,分组时要使用其自动生成的.keyword子字段,否则会因分词导致分组结果错乱 - 需要累加的数值字段必须是ES支持的数值类型(long/integer/double/float等),如果存成字符串类型无法执行sum聚合,需要先调整映射重新导入数据
- 分组用的网站字段
- 调整原有查询语句
你原语句里设置"size":4000是返回最多4000条原始文档,聚合场景不需要返回原始文档,把size设为0即可大幅降低网络传输开销。 - 完整可运行的查询示例
注意把示例里的metric_value替换成你实际存储关联数值的字段名:
{ "size": 0, "query": { "exists": { "field": "site.website" } }, "aggs": { "site_groups": { "terms": { "field": "site.website", "size": 1000 // 这里设置最多返回多少个网站的统计结果,根据你实际的网站总量调整,默认值为10 }, "aggs": { "num_sum": { "sum": { "field": "metric_value" // 替换为你自己的数值字段名 } } } } } }
- 结果读取
查询返回的结果中,aggregations.site_groups.buckets数组就是分组统计结果,每个数组元素的结构:key:对应的网站域名/标识doc_count:该网站下匹配查询条件的记录总条数num_sum.value:该网站对应的数值累加总和
注意:如果你的网站总数量超过terms聚合里设置的size参数,返回结果会做截断,需要根据实际站点规模调大size值;如果站点量级极大(十万级以上),可以配合复合聚合做分批拉取,普通业务场景调大size即可满足需求。
内容的提问来源于stack exchange,提问作者Victoire
相关产品推荐
相关产品推荐

