ElasticSearch全文搜索引擎之Aggregation聚合查询(基于RestHighLevelClient)
目录
一、简介
二、度量查询
三、桶查询
四、嵌套查询
五、总结
一、简介
前面一篇文章我们已经通过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)相关推荐
- ElasticSearch 全文搜索引擎的查询详解①(Ubuntu版 v6.6.2)
ElasticSearch 全文搜索引擎的查询详解①(Ubuntu版 v6.6.2) 1. 前提 2. 轻量搜索 2.1 单条件查询 2.2 多条件查询 2.3 不指定属性查询(查询所有文档属性)-- ...
- 一文看懂-ElasticSearch全文搜索引擎
一文看懂-ElasticSearch全文搜索引擎 一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic 从名字里我们可以 ...
- PHP使用Elasticsearch 全文搜索引擎的开发
PHP基于elasticsearch全文搜索引擎的开发 1.概述: 全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选.Elastic ...
- Elasticsearch全文搜索引擎-PHP使用教程。
1.声明依赖关系: 比方说,你的项目中需要一个php版的elasticsearch框架.为了将它添加到你的项目中(下载),你所需要做的就是创建一个 composer.json 文件,其 ...
- ElasticSearch 全文搜索引擎
一.ElasticSearch 简介 1.什么是 ElasticSearch? Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本身 ...
- ElasticSearch 全文搜索引擎;ES 搜索引擎
一.ElasticSearch 简介 1.什么是 ElasticSearch? Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本身 ...
- Elasticsearch全文搜索引擎,从0到0.6
目录 一,ES简介 1,es实现原理 2,基本结构 3,ELK 二.Linux搭建环境 1,jdk安装 2,安装Elasticsearch 3,启动es 4,启动es可能遇到的错误 4,在windon ...
- ElasticSearch全文搜索引擎
一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic 从名字里我们可以知道,ES的特点就在于灵活的搜索,其实E ...
- ElasticSearch——全文搜索引擎
一.为什么需要全文搜索引擎? 首先先来了解一个概念,在我们生活中一般来说有两种数据:结构化数据.非结构化数据 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等. 非结构化数据: 非结构化 ...
- Mongodb使用之Aggregation聚合查询:.group()/.project()/.and().previousOperation()等api的使用
最近在项目中遇到了Mongodb在聚合查询上的应用,在这里做一个记录. Spring Data MongoDB 中的聚合框架支持基于以下关键抽象:Aggregation.AggregationDefi ...
最新文章
- Github 年度最受欢迎的 TOP30 Python 项目,超值
- 最后一条记录_幸好朋友圈没有访客记录。
- Python 3 Basics
- Weblogic负载均衡/Session复制之集群架构
- start_kernel之前的调用流程(head.s)
- 「Leetcode」707.设计链表:一道题目考察了常见的五个操作!
- 宾州州立计算机科学世界排名,美国宾州州立大学排名一览表:世界综排与专业排名详细解析!...
- 云服务器怎么多人进去编辑文档,服务器如何设置多人登陆
- QFIL的烧录、读写
- 支付宝口碑收款码(详细解析)
- 动态生成icon图标
- C语言变量及其生命周期
- P9 力荐!阿里巴巴最新出品 776 页 JDK 源码 + 并发核心原理解析小册
- pythonyaml参数传递_configutator-将yaml节点和命令行参数映射到python函数参数。-Nolan configutator To use:...
- HTML中文字间距调整
- 电脑蓝屏原因与手把手处理指南(关于0x00000124分析)
- Should we ban guns 英语禁枪议论文
- ITSM常见问题之:自动指派工单给对应的技术员的三种简单方法
- 想创业 就别输不起 --leo看赢在中国第三季 7
- 【STM32单片机-库函数】继电器——relay
热门文章
- matlab程序中中零内插在qdpsk调制中的作用,桂林电子科技大学通信原理思考题
- 机器学习- 吴恩达Andrew Ng Week6 Regularized Linear Regression and Bias/Variance知识总结
- 2021-08-27 BERT4Rec简介
- 636. 函数的独占时间
- 532. 数组中的K-diff数对
- 32个参数累加_「机械设计教程」滚珠丝杠选型过程中考虑的9个参数
- python 京东 价格_python根据京东商品url获取产品价格
- 算法中的最优化方法_学习目录
- 2018_09_21_生活记录_参加人工智能大会
- 最新原生nodejs调试器的使用大全详解