ElasticSearch里面的聚合机制非常灵活和强大,今天我们来看下如何在ElasticSearch里面实现分组后,根据sum值进行排序?类似的数据库SQL如下:
select id,sum(c1) as c1 , sum(c2) as c2 from table1 group id order by c1 desc, c2 asc
这是一个比较常见的统计需求,在es也能比较轻松的实现,先看看curl的一个实现例子查询:
GET myindex/_search { "size":0, "aggs": { "a1": { "terms": { "field": "FIELD1", "size":0, "order": {"a2": "desc"} }, "aggs":{ "a2":{ "sum":{ "field":"FIELD2.SUBFIELD" } } } } } }
然后,我们看下,如何在Java Api里面操作:
首先我们看下造的数据
总共三个字段id,count,code都是int类型的
id,count,code 1,3,1 2,4,1 1,5,2 2,7,1 3,11,7
然后,我们可以将上面的数据插入到es里面,具体的插入代码不在给出,比较简单,直接通过client.prepareIndex方法插入json即可。
下面看下查询代码:
public void groupTest(){ //构建查询请求体 SearchRequestBuilder search = client.prepareSearch("gv_test").setTypes("gv_test"); //分组字段是id,排序由多个字段排序组成 TermsBuilder tb= AggregationBuilders.terms("id").field("id").order(Terms.Order.compound( Terms.Order.aggregation("sum_count",false)//先按count,降序排 , Terms.Order.aggregation("sum_code",true)//如果count相等情况下,使用code的和排序 )); //求和字段1 SumBuilder sb= AggregationBuilders.sum("sum_count").field("count"); //求和字段2 SumBuilder sb_code= AggregationBuilders.sum("sum_code").field("code"); tb.subAggregation(sb);//添加到分组聚合请求中 tb.subAggregation(sb_code);//添加到分组聚合请求中 //将分组聚合请求插入到主请求体重 search.addAggregation(tb); //发送查询,获取聚合结果 Terms tms= search.get().getAggregations().get("id"); //遍历每一个分组的key for(Terms.Bucket tbb:tms.getBuckets()){ //获取count的和 Sum sum= tbb.getAggregations().get("sum_count"); //获取code的和 Sum sum2=tbb.getAggregations().get("sum_code"); System.out.println(tbb.getKey()+" " + tbb.getDocCount() +" "+sum.getValue()+" "+sum2.getValue()); } //释放资源 client.close(); }
最终的结果如下:
id,分组个数,count的和,code和 2 2 11.0 2.0 3 1 11.0 7.0 1 2 8.0 3.0
通过对比,我们可以到到结果是准确的,虽然代码量比sql多很多,但是ElasticSearch的聚合功能却是非常的强大和灵活,用来做一些OLAP分析是非常方便的。
有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。
技术债不能欠,健康债更不能欠, 求道之路,与君同行。