如何使用Elasticsearch聚合实现数组对应位置元素求和
Elasticsearch 数组对应位置元素求和实现方案
方案1:固定长度数组(推荐,性能最优)
如果你的arr字段长度固定(如示例中均为5个元素),可直接对数组每个位置的元素单独求和,查询DSL如下:
{ "size": 0, "aggs": { "sum_pos0": { "sum": { "field": "arr.0" } }, "sum_pos1": { "sum": { "field": "arr.1" } }, "sum_pos2": { "sum": { "field": "arr.2" } }, "sum_pos3": { "sum": { "field": "arr.3" } }, "sum_pos4": { "sum": { "field": "arr.4" } } } }
返回的聚合结果中,把sum_pos0到sum_pos4的结果按顺序拼接,即可得到你需要的[10,7,5,3,1]数组。
方案2:动态长度数组(适配长度不固定的场景)
如果数组长度不固定,可使用scripted_metric脚本聚合实现,查询DSL如下:
{ "size": 0, "aggs": { "arr_total_sum": { "scripted_metric": { "init_script": "state.sum_arr = []", "map_script": """ for(int i=0;i<doc['arr'].length;i++){ if(state.sum_arr.size() <= i) state.sum_arr.add(0L); state.sum_arr.set(i, state.sum_arr.get(i) + doc['arr'].get(i)); } """, "combine_script": "return state.sum_arr", "reduce_script": """ List final_sum = []; for(shard_sum in states){ for(int i=0;i<shard_sum.size();i++){ if(final_sum.size() <= i) final_sum.add(0L); final_sum.set(i, final_sum.get(i) + shard_sum.get(i)); } } return final_sum; """ } } } }
返回的arr_total_sum值就是你需要的汇总数组。
注意事项
- 方案2需要ES集群开启inline脚本权限,默认配置支持,如遇权限报错可检查
script.allowed_types配置项 - 数组长度固定的场景优先使用方案1,性能远高于脚本聚合
内容的提问来源于stack exchange,提问作者Dimple Goyal
相关产品推荐
相关产品推荐

