目录

一、简介

二、度量查询

三、桶查询

四、嵌套查询

五、总结


一、简介

前面一篇文章我们已经通过DSL构建JSON查询请求体,并且结合Kibana介绍了常见的聚合查询,本篇文章主要是结合ES Java 高级API实现聚合查询,工作中更多的时候都是使用客户端进行操作,使用命令太繁琐了。

二、度量查询

测试数据还是跟前面一篇文章一致,这里就不过多阐述,详细可以参照上文,执行脚本如下:

# 批量插入测试数据
POST /user/info/_bulk
{"index":{"_id":1}}
{"name":"zs","realname":"张三","age":10,"birthday":"2018-12-27","salary":1000.0,"address":"广州市天河区科韵路50号"}
{"index":{"_id":2}}
{"name":"ls","realname":"李四","age":20,"birthday":"2017-10-20","salary":2000.0,"address":"广州市天河区珠江新城"}
{"index":{"_id":3}}
{"name":"ww","realname":"王五","age":30,"birthday":"2016-03-15","salary":3000.0,"address":"广州市天河区广州塔"}
{"index":{"_id":4}}
{"name":"zl","realname":"赵六","age":40,"birthday":"2003-04-19","salary":4000.0,"address":"广州市海珠区"}
{"index":{"_id":5}}
{"name":"tq","realname":"田七","age":50,"birthday":"2001-08-11","salary":5000.0,"address":"广州市天河区网易大厦"}

【a】平均值聚合查询

AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("avg_salary").field("salary")

如:求员工平均工资

/*** 平均值聚合查询: AggregationBuilders.avg("avg_salary").field("salary")*/@Testvoid avgAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//平均值聚合查询: 求员工平均工资AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("avg_salary").field("salary");searchSourceBuilder.aggregation(avgAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("avg_salary")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"asMap":{"avg_salary":{"fragment":true,"name":"avg_salary","type":"avg","value":3000.0,"valueAsString":"3000.0"}},"fragment":true}
{"fragment":true,"name":"avg_salary","type":"avg","value":3000.0,"valueAsString":"3000.0"}

【b】最大值聚合查询

MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("max_salary").field("salary")

如:求员工最高工资

/*** 最大值聚合查询: AggregationBuilders.max("max_salary").field("salary")*/@Testvoid maxAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//求员工最高工资MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("max_salary").field("salary");searchSourceBuilder.aggregation(maxAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("max_salary")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":5000.0,"valueAsString":"5000.0"}},"fragment":true}
{"fragment":true,"name":"max_salary","type":"max","value":5000.0,"valueAsString":"5000.0"}

【c】最小值聚合查询

MinAggregationBuilder minAggregationBuilder = AggregationBuilders.min("min_salary").field("salary")

如:求员工最低工资

/*** 最小值聚合查询: AggregationBuilders.min("min_salary").field("salary")*/@Testvoid minAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//求员工最低工资MinAggregationBuilder minAggregationBuilder = AggregationBuilders.min("min_salary").field("salary");searchSourceBuilder.aggregation(minAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("min_salary")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"asMap":{"min_salary":{"fragment":true,"name":"min_salary","type":"min","value":1000.0,"valueAsString":"1000.0"}},"fragment":true}
{"fragment":true,"name":"min_salary","type":"min","value":1000.0,"valueAsString":"1000.0"}

【d】求和聚合查询

SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("sum_salary").field("salary")

如:求所有员工总工资

 /*** 求和聚合查询: AggregationBuilders.sum("sum_salary").field("salary")*/@Testvoid sumAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//求员工总工资SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("sum_salary").field("salary");searchSourceBuilder.aggregation(sumAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("sum_salary")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果如下:

{"asMap":{"sum_salary":{"fragment":true,"name":"sum_salary","type":"sum","value":15000.0,"valueAsString":"15000.0"}},"fragment":true}
{"fragment":true,"name":"sum_salary","type":"sum","value":15000.0,"valueAsString":"15000.0"}

【e】stats聚合查询

StatsAggregationBuilder statsAggregationBuilder = AggregationBuilders.stats("stats_salary").field("salary")

如:一次性查询出员工最低工资、最高工资、总工资等

/*** stats聚合查询: AggregationBuilders.stats("stats_salary").field("salary")*/@Testvoid statsAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统一求员工最低工资、最高工资、总工资等StatsAggregationBuilder statsAggregationBuilder = AggregationBuilders.stats("stats_salary").field("salary");searchSourceBuilder.aggregation(statsAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("stats_salary")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"asMap":{"stats_salary":{"avg":3000.0,"avgAsString":"3000.0","count":5,"fragment":true,"max":5000.0,"maxAsString":"5000.0","min":1000.0,"minAsString":"1000.0","name":"stats_salary","sum":15000.0,"sumAsString":"15000.0","type":"stats"}},"fragment":true}
{"avg":3000.0,"avgAsString":"3000.0","count":5,"fragment":true,"max":5000.0,"maxAsString":"5000.0","min":1000.0,"minAsString":"1000.0","name":"stats_salary","sum":15000.0,"sumAsString":"15000.0","type":"stats"}

【f】value count聚合查询

ValueCountAggregationBuilder valueCountAggregationBuilder = AggregationBuilders.count("price_value_count").field("salary")

如:统计工资字段有值的文档数目

/*** value count聚合查询: AggregationBuilders.count("price_value_count").field("salary")*/@Testvoid valueCountAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统计某字段有值的文档数ValueCountAggregationBuilder valueCountAggregationBuilder = AggregationBuilders.count("price_value_count").field("salary");searchSourceBuilder.aggregation(valueCountAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();System.out.println(JSON.toJSONString(aggregations));System.out.println(JSON.toJSONString(aggregations.getAsMap().get("price_value_count")));} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"asMap":{"price_value_count":{"fragment":true,"name":"price_value_count","type":"value_count","value":5,"valueAsString":"5.0"}},"fragment":true}
{"fragment":true,"name":"price_value_count","type":"value_count","value":5,"valueAsString":"5.0"}

三、桶查询

【a】range范围桶聚合查询

RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("age_ranges_count").field("age").addRange(0, 20).addRange(20, 40).addRange(40, 60)

如:统计0-20岁,20-40岁,40~60岁各个区间段的员工人数

/*** range范围桶聚合查询: AggregationBuilders.range("age_ranges_count").field("age").addRange(0, 20).addRange(20, 40).addRange(40, 60)*/@Testvoid rangeAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统计0-20岁,20-40岁,40~60岁各个区间段的用户人数RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("age_ranges_count").field("age").addRange(0, 20).addRange(20, 40).addRange(40, 60);searchSourceBuilder.aggregation(rangeAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("age_ranges_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Range.Bucket> buckets = ((Range) aggregation).getBuckets();//循环遍历各个桶结果for (Range.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();//分组的值long docCount = bucket.getDocCount();System.out.println(key + "------->" + docCount);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"from":0.0,"fromAsString":"0.0","key":"0.0-20.0","keyAsString":"0.0-20.0","to":20.0,"toAsString":"20.0"},{"aggregations":{"asMap":{},"fragment":true},"docCount":2,"fragment":true,"from":20.0,"fromAsString":"20.0","key":"20.0-40.0","keyAsString":"20.0-40.0","to":40.0,"toAsString":"40.0"},{"aggregations":{"asMap":{},"fragment":true},"docCount":2,"fragment":true,"from":40.0,"fromAsString":"40.0","key":"40.0-60.0","keyAsString":"40.0-60.0","to":60.0,"toAsString":"60.0"}],"fragment":true,"name":"age_ranges_count","type":"range"}
0.0-20.0------->1
20.0-40.0------->2
40.0-60.0------->2

【b】term自定义分组桶聚合查询

TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("age_count").field("age").size(3)

如:根据年龄分组,统计相同年龄的用户,并只返回3条记录

/*** term自定义分组桶聚合查询: AggregationBuilders.terms("age_count").field("age").size(3)*/@Testvoid termsAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//根据年龄分组,统计相同年龄的用户,并只返回3条记录TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("age_count").field("age").size(3);searchSourceBuilder.aggregation(termsAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("age_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Terms.Bucket> buckets = ((Terms) aggregation).getBuckets();//循环遍历各个桶结果for (Terms.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();//分组的值long docCount = bucket.getDocCount();System.out.println(key + "------->" + docCount);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"docCountError":0,"fragment":true,"key":10,"keyAsNumber":10,"keyAsString":"10"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"docCountError":0,"fragment":true,"key":20,"keyAsNumber":20,"keyAsString":"20"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"docCountError":0,"fragment":true,"key":30,"keyAsNumber":30,"keyAsString":"30"}],"docCountError":0,"fragment":true,"name":"age_count","sumOfOtherDocCounts":2,"type":"lterms"}
10------->1
20------->1
30------->1

【c】日期范围分组桶聚合查询

DateRangeAggregationBuilder dateRangeAggregationBuilder = AggregationBuilders.dateRange("birthday_count").field("birthday").addRange("now/y-1y", "now/y").addRange("now/y-2y", "now/y-1y").addRange("now/y-3y", "now/y-2y").format("yyyy-MM-dd")

如:统计生日在2017年、2018年、2019年的员工

/*** 日期范围分组桶聚合查询: AggregationBuilders.dateRange("birthday_count").field("birthday").addRange("now/y-1y", "now/y").addRange("now/y-2y", "now/y-1y").addRange("now/y-3y", "now/y-2y").format("yyyy-MM-dd")*/@Testvoid dateRangeAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统计生日在2017年、2018年、2019年的用户DateRangeAggregationBuilder dateRangeAggregationBuilder = AggregationBuilders.dateRange("birthday_count").field("birthday").addRange("now/y-1y", "now/y")  //  now/y:当前年的1月1日  now:当前时间.addRange("now/y-2y", "now/y-1y")  //  now/y-1y:当前年上一年的1月1日.addRange("now/y-3y", "now/y-2y").format("yyyy-MM-dd");searchSourceBuilder.aggregation(dateRangeAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("birthday_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Range.Bucket> buckets = ((Range) aggregation).getBuckets();//循环遍历各个桶结果for (Range.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();//分组的值long docCount = bucket.getDocCount();System.out.println(key + "------->" + docCount);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"from":"2017-01-01T00:00Z","fromAsString":"2017-01-01","key":"2017-01-01-2018-01-01","keyAsString":"2017-01-01-2018-01-01","to":"2018-01-01T00:00Z","toAsString":"2018-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"from":"2018-01-01T00:00Z","fromAsString":"2018-01-01","key":"2018-01-01-2019-01-01","keyAsString":"2018-01-01-2019-01-01","to":"2019-01-01T00:00Z","toAsString":"2019-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"from":"2019-01-01T00:00Z","fromAsString":"2019-01-01","key":"2019-01-01-2020-01-01","keyAsString":"2019-01-01-2020-01-01","to":"2020-01-01T00:00Z","toAsString":"2020-01-01"}],"fragment":true,"name":"birthday_count","type":"date_range"}
2017-01-01-2018-01-01------->1
2018-01-01-2019-01-01------->1
2019-01-01-2020-01-01------->0

【d】直方图桶聚合查询

HistogramAggregationBuilder histogramAggregationBuilder = AggregationBuilders.histogram("age_histogram_count").field("age").interval(20)

如:根据年龄间隔(20岁)统计各个年龄段的员工总人数

/*** 直方图桶聚合查询: AggregationBuilders.histogram("age_histogram_count").field("age").interval(20);*/@Testvoid histogramAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//根据年龄间隔(20岁)统计各个年龄段的员工总人数HistogramAggregationBuilder histogramAggregationBuilder = AggregationBuilders.histogram("age_histogram_count").field("age").interval(20);searchSourceBuilder.aggregation(histogramAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("age_histogram_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Histogram.Bucket> buckets = ((Histogram) aggregation).getBuckets();//循环遍历各个桶结果for (Histogram.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();//分组的值long docCount = bucket.getDocCount();System.out.println(key + "------->" + docCount);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":0.0,"keyAsString":"0.0"},{"aggregations":{"asMap":{},"fragment":true},"docCount":2,"fragment":true,"key":20.0,"keyAsString":"20.0"},{"aggregations":{"asMap":{},"fragment":true},"docCount":2,"fragment":true,"key":40.0,"keyAsString":"40.0"}],"fragment":true,"name":"age_histogram_count","type":"histogram"}
0.0------->1
20.0------->2
40.0------->2

【e】日期直方图桶聚合查询

DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("birthday_data_histogram_count").field("birthday").calendarInterval(DateHistogramInterval.YEAR).format("yyyy-MM-dd");

如:按年统计员工生日的总人数

/*** 日期直方图桶聚合查询: AggregationBuilders.dateHistogram("birthday_data_histogram_count").field("birthday").calendarInterval(DateHistogramInterval.YEAR).format("yyyy-MM-dd");*/@Testvoid dateHistogramAggregation() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//按年统计用户生日的总人数DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("birthday_data_histogram_count").field("birthday").calendarInterval(DateHistogramInterval.YEAR).format("yyyy-MM-dd");searchSourceBuilder.aggregation(dateHistogramAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("birthday_data_histogram_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Histogram.Bucket> buckets = ((Histogram) aggregation).getBuckets();//循环遍历各个桶结果for (Histogram.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();//分组的值long docCount = bucket.getDocCount();System.out.println(key + "------->" + docCount);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":"2001-01-01T00:00Z","keyAsString":"2001-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2002-01-01T00:00Z","keyAsString":"2002-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":"2003-01-01T00:00Z","keyAsString":"2003-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2004-01-01T00:00Z","keyAsString":"2004-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2005-01-01T00:00Z","keyAsString":"2005-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2006-01-01T00:00Z","keyAsString":"2006-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2007-01-01T00:00Z","keyAsString":"2007-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2008-01-01T00:00Z","keyAsString":"2008-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2009-01-01T00:00Z","keyAsString":"2009-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2010-01-01T00:00Z","keyAsString":"2010-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2011-01-01T00:00Z","keyAsString":"2011-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2012-01-01T00:00Z","keyAsString":"2012-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2013-01-01T00:00Z","keyAsString":"2013-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2014-01-01T00:00Z","keyAsString":"2014-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":0,"fragment":true,"key":"2015-01-01T00:00Z","keyAsString":"2015-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":"2016-01-01T00:00Z","keyAsString":"2016-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":"2017-01-01T00:00Z","keyAsString":"2017-01-01"},{"aggregations":{"asMap":{},"fragment":true},"docCount":1,"fragment":true,"key":"2018-01-01T00:00Z","keyAsString":"2018-01-01"}],"fragment":true,"name":"birthday_data_histogram_count","type":"date_histogram"}
2001-01-01------->1
2002-01-01------->0
2003-01-01------->1
2004-01-01------->0
2005-01-01------->0
2006-01-01------->0
2007-01-01------->0
2008-01-01------->0
2009-01-01------->0
2010-01-01------->0
2011-01-01------->0
2012-01-01------->0
2013-01-01------->0
2014-01-01------->0
2015-01-01------->0
2016-01-01------->1
2017-01-01------->1
2018-01-01------->1

四、嵌套查询

使用RestHighLevelClient实现嵌套聚合查询主要通过下面的代码实现,通过设置subAggregation实现。

xxxAggregationBuilder.subAggregation(xxxAggregationBuilder);

下面通过两个案例介绍es中嵌套聚合查询如何实现。

  • 示例一: 统计每年中用户的最高工资
/*** 示例一: 统计每年中用户的最高工资*/@Testvoid countEveryYearMaxSalary() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统计每年中用户的最高工资DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("birthday_data_histogram_count").field("birthday").calendarInterval(DateHistogramInterval.YEAR).format("yyyy-MM-dd");//嵌套子聚合查询MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("max_salary").field("salary");dateHistogramAggregationBuilder.subAggregation(maxAggregationBuilder);searchSourceBuilder.aggregation(dateHistogramAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("birthday_data_histogram_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Histogram.Bucket> buckets = ((Histogram) aggregation).getBuckets();//循环遍历各个桶结果for (Histogram.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();Aggregations subAggregations = bucket.getAggregations();Aggregation maxSalaryAggregation = subAggregations.getAsMap().get("max_salary");System.out.println(JSON.toJSONString(maxSalaryAggregation));Map<String, Object> maxSalaryMap = (Map<String, Object>) JSONObject.parse(JSON.toJSONString(maxSalaryAggregation));String maxSalary = null != maxSalaryMap.get("value") ? maxSalaryMap.get("value").toString() : "";System.out.println(key + "------->" + maxSalary);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":5000.0,"valueAsString":"5000.0"}},"fragment":true},"docCount":1,"fragment":true,"key":"2001-01-01T00:00Z","keyAsString":"2001-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2002-01-01T00:00Z","keyAsString":"2002-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":4000.0,"valueAsString":"4000.0"}},"fragment":true},"docCount":1,"fragment":true,"key":"2003-01-01T00:00Z","keyAsString":"2003-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2004-01-01T00:00Z","keyAsString":"2004-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2005-01-01T00:00Z","keyAsString":"2005-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2006-01-01T00:00Z","keyAsString":"2006-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2007-01-01T00:00Z","keyAsString":"2007-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2008-01-01T00:00Z","keyAsString":"2008-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2009-01-01T00:00Z","keyAsString":"2009-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2010-01-01T00:00Z","keyAsString":"2010-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2011-01-01T00:00Z","keyAsString":"2011-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2012-01-01T00:00Z","keyAsString":"2012-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2013-01-01T00:00Z","keyAsString":"2013-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2014-01-01T00:00Z","keyAsString":"2014-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}},"fragment":true},"docCount":0,"fragment":true,"key":"2015-01-01T00:00Z","keyAsString":"2015-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":3000.0,"valueAsString":"3000.0"}},"fragment":true},"docCount":1,"fragment":true,"key":"2016-01-01T00:00Z","keyAsString":"2016-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":2000.0,"valueAsString":"2000.0"}},"fragment":true},"docCount":1,"fragment":true,"key":"2017-01-01T00:00Z","keyAsString":"2017-01-01"},{"aggregations":{"asMap":{"max_salary":{"fragment":true,"name":"max_salary","type":"max","value":1000.0,"valueAsString":"1000.0"}},"fragment":true},"docCount":1,"fragment":true,"key":"2018-01-01T00:00Z","keyAsString":"2018-01-01"}],"fragment":true,"name":"birthday_data_histogram_count","type":"date_histogram"}
{"fragment":true,"name":"max_salary","type":"max","value":5000.0,"valueAsString":"5000.0"}
2001-01-01------->5000.0
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2002-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":4000.0,"valueAsString":"4000.0"}
2003-01-01------->4000.0
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2004-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2005-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2006-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2007-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2008-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2009-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2010-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2011-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2012-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2013-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2014-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":null,"valueAsString":"-Infinity"}
2015-01-01------->
{"fragment":true,"name":"max_salary","type":"max","value":3000.0,"valueAsString":"3000.0"}
2016-01-01------->3000.0
{"fragment":true,"name":"max_salary","type":"max","value":2000.0,"valueAsString":"2000.0"}
2017-01-01------->2000.0
{"fragment":true,"name":"max_salary","type":"max","value":1000.0,"valueAsString":"1000.0"}
2018-01-01------->1000.0
  • 示例二: 统计每个年龄区间段的工资总和
/*** 示例二: 统计每个年龄区间段的工资总和*/@Test@SuppressWarnings("unchecked")void countEveryRangeAgeSumSalary() throws IOException {//创建一个查询请求,并指定索引名称SearchRequest searchRequest = new SearchRequest("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//统计每年中用户的最高工资DateRangeAggregationBuilder dateRangeAggregationBuilder = AggregationBuilders.dateRange("age_ranges_count").field("age").addRange(0, 20).addRange(20, 40).addRange(40, 60);//嵌套子聚合查询SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("sum_salary").field("salary");dateRangeAggregationBuilder.subAggregation(sumAggregationBuilder);searchSourceBuilder.aggregation(dateRangeAggregationBuilder);searchRequest.source(searchSourceBuilder);SearchResponse response;try {//发起请求,获取响应结果response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//获取聚合的结果Aggregations aggregations = response.getAggregations();Aggregation aggregation = aggregations.get("age_ranges_count");System.out.println(JSON.toJSONString(aggregation));//获取桶聚合结果List<? extends Range.Bucket> buckets = ((Range) aggregation).getBuckets();//循环遍历各个桶结果for (Range.Bucket bucket : buckets) {//分组的keyString key = bucket.getKeyAsString();Aggregations subAggregations = bucket.getAggregations();Aggregation maxSalaryAggregation = subAggregations.getAsMap().get("sum_salary");System.out.println(JSON.toJSONString(maxSalaryAggregation));Map<String, Object> sumSalaryMap = (Map<String, Object>) JSONObject.parse(JSON.toJSONString(maxSalaryAggregation));String maxSalary = null != sumSalaryMap.get("value") ? sumSalaryMap.get("value").toString() : "";System.out.println(key + "------->" + maxSalary);}} catch (IOException e) {e.printStackTrace();}//关闭restHighLevelClientrestHighLevelClient.close();}

响应结果:

{"buckets":[{"aggregations":{"asMap":{"sum_salary":{"fragment":true,"name":"sum_salary","type":"sum","value":1000.0,"valueAsString":"1000.0"}},"fragment":true},"docCount":1,"fragment":true,"from":"1970-01-01T00:00Z","fromAsString":"0.0","key":"0.0-20.0","keyAsString":"0.0-20.0","to":"1970-01-01T00:00:00.020Z","toAsString":"20.0"},{"aggregations":{"asMap":{"sum_salary":{"fragment":true,"name":"sum_salary","type":"sum","value":5000.0,"valueAsString":"5000.0"}},"fragment":true},"docCount":2,"fragment":true,"from":"1970-01-01T00:00:00.020Z","fromAsString":"20.0","key":"20.0-40.0","keyAsString":"20.0-40.0","to":"1970-01-01T00:00:00.040Z","toAsString":"40.0"},{"aggregations":{"asMap":{"sum_salary":{"fragment":true,"name":"sum_salary","type":"sum","value":9000.0,"valueAsString":"9000.0"}},"fragment":true},"docCount":2,"fragment":true,"from":"1970-01-01T00:00:00.040Z","fromAsString":"40.0","key":"40.0-60.0","keyAsString":"40.0-60.0","to":"1970-01-01T00:00:00.060Z","toAsString":"60.0"}],"fragment":true,"name":"age_ranges_count","type":"date_range"}
{"fragment":true,"name":"sum_salary","type":"sum","value":1000.0,"valueAsString":"1000.0"}
0.0-20.0------->1000.0
{"fragment":true,"name":"sum_salary","type":"sum","value":5000.0,"valueAsString":"5000.0"}
20.0-40.0------->5000.0
{"fragment":true,"name":"sum_salary","type":"sum","value":9000.0,"valueAsString":"9000.0"}
40.0-60.0------->9000.0

五、总结

本篇文章主要总结了使用RestHighLevelClient客户端实现ES聚合查询,通过示例介绍了一些常见的聚合查询,希望能对小伙伴们的学习有所帮助,由于笔者水平有限,可能存在不对之处,还望指正,相互学习,一起进步!

ElasticSearch全文搜索引擎之Aggregation聚合查询(基于RestHighLevelClient)相关推荐

  1. ElasticSearch 全文搜索引擎的查询详解①(Ubuntu版 v6.6.2)

    ElasticSearch 全文搜索引擎的查询详解①(Ubuntu版 v6.6.2) 1. 前提 2. 轻量搜索 2.1 单条件查询 2.2 多条件查询 2.3 不指定属性查询(查询所有文档属性)-- ...

  2. 一文看懂-ElasticSearch全文搜索引擎

    一文看懂-ElasticSearch全文搜索引擎 一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic 从名字里我们可以 ...

  3. PHP使用Elasticsearch 全文搜索引擎的开发

    PHP基于elasticsearch全文搜索引擎的开发 1.概述: 全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选.Elastic ...

  4. Elasticsearch全文搜索引擎-PHP使用教程。

    1.声明依赖关系:         比方说,你的项目中需要一个php版的elasticsearch框架.为了将它添加到你的项目中(下载),你所需要做的就是创建一个 composer.json 文件,其 ...

  5. ElasticSearch 全文搜索引擎

    一.ElasticSearch 简介 1.什么是 ElasticSearch? Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本身 ...

  6. ElasticSearch 全文搜索引擎;ES 搜索引擎

    一.ElasticSearch 简介 1.什么是 ElasticSearch? Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本身 ...

  7. Elasticsearch全文搜索引擎,从0到0.6

    目录 一,ES简介 1,es实现原理 2,基本结构 3,ELK 二.Linux搭建环境 1,jdk安装 2,安装Elasticsearch 3,启动es 4,启动es可能遇到的错误 4,在windon ...

  8. ElasticSearch全文搜索引擎

    一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic      从名字里我们可以知道,ES的特点就在于灵活的搜索,其实E ...

  9. ElasticSearch——全文搜索引擎

    一.为什么需要全文搜索引擎? 首先先来了解一个概念,在我们生活中一般来说有两种数据:结构化数据.非结构化数据 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等. 非结构化数据: 非结构化 ...

  10. Mongodb使用之Aggregation聚合查询:.group()/.project()/.and().previousOperation()等api的使用

    最近在项目中遇到了Mongodb在聚合查询上的应用,在这里做一个记录. Spring Data MongoDB 中的聚合框架支持基于以下关键抽象:Aggregation.AggregationDefi ...

最新文章

  1. Github 年度最受欢迎的 TOP30 Python 项目,超值
  2. 最后一条记录_幸好朋友圈没有访客记录。
  3. Python 3 Basics
  4. Weblogic负载均衡/Session复制之集群架构
  5. start_kernel之前的调用流程(head.s)
  6. 「Leetcode」707.设计链表:一道题目考察了常见的五个操作!
  7. 宾州州立计算机科学世界排名,美国宾州州立大学排名一览表:世界综排与专业排名详细解析!...
  8. 云服务器怎么多人进去编辑文档,服务器如何设置多人登陆
  9. QFIL的烧录、读写
  10. 支付宝口碑收款码(详细解析)
  11. 动态生成icon图标
  12. C语言变量及其生命周期
  13. P9 力荐!阿里巴巴最新出品 776 页 JDK 源码 + 并发核心原理解析小册
  14. pythonyaml参数传递_configutator-将yaml节点和命令行参数映射到python函数参数。-Nolan configutator To use:...
  15. HTML中文字间距调整
  16. 电脑蓝屏原因与手把手处理指南(关于0x00000124分析)
  17. Should we ban guns 英语禁枪议论文
  18. ITSM常见问题之:自动指派工单给对应的技术员的三种简单方法
  19. 想创业 就别输不起 --leo看赢在中国第三季 7
  20. 【STM32单片机-库函数】继电器——relay

热门文章

  1. matlab程序中中零内插在qdpsk调制中的作用,桂林电子科技大学通信原理思考题
  2. 机器学习- 吴恩达Andrew Ng Week6 Regularized Linear Regression and Bias/Variance知识总结
  3. 2021-08-27 BERT4Rec简介
  4. 636. 函数的独占时间
  5. 532. 数组中的K-diff数对
  6. 32个参数累加_「机械设计教程」滚珠丝杠选型过程中考虑的9个参数
  7. python 京东 价格_python根据京东商品url获取产品价格
  8. 算法中的最优化方法_学习目录
  9. 2018_09_21_生活记录_参加人工智能大会
  10. 最新原生nodejs调试器的使用大全详解