官方文档介绍:https://www.elastic.co/guide/cn/elasticsearch/guide/current/aggs-high-level.html
可以结合官方文档和这篇文章去学习。相关代码可在资源界面获取。
聚合是桶和指标组成的
当聚合开始执行时,每个文档里面的值通过计算来决定符合哪个桶,如果匹配,文档将会被放入对应的桶中
桶
满足特定条件的文档 相当于sql的group by。
多个嵌套级的aggregation,类似于sql多字段分组(group by field1,field2)
指标
对桶内的文档进行统计计算 相当于count(),sum(),max()等统计方法
POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2014-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2014-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" }
聚合可以和搜索请求同时进行,默认情况下,聚合与查询是对同一范围进行操作的,也就是说,聚合是基于我们查询的文档集合进行计算的
全文查询和聚合
例一:不同颜色的车分别有多少辆
popular_colors为桶的名称
terms为桶的类型
GET /cars/transactions/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color.keyword"
}
}
}
}
//聚合 不同颜色的车分别有多少辆
@Test
public void aagsTest() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest();
//构建查询创建者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//添加聚合条件
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.
terms("popular_colors").//设置一个桶的名字 取结果的时候需要用到
field("color.keyword"); // 聚合的字段 color类型为text 取类型为keyword的子字段color.keyword
ssb.aggregation(aggregationBuilder);
request.indices("cars");
request.source(ssb);
//执行查询返回查询响应结果
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//取结果
Terms aggs = search.getAggregations().get("popular_colors");
for (Terms.Bucket bucket : aggs.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());
}
}
注意:ES在聚合时的字段类型不能为text,但是一般text字段有一个类型为keyword的子字段keyword,keyword类型可以排序和聚合,可以是用字段.子字段,如上面的例子。
类型keyword与text的区别: keyword只能精确查询,不能被分词查询,能聚合、排序。 text类型能模糊查询,能分词查询,不能聚合、排序。
例二:各种颜色车辆平均价格以及代码
get /cars/transactions/_search
{
"aggs":{
"popular_colors" :{
"terms":{
"field": "color.keyword"
},
"aggs":{
"avg_price":{
"avg":{
"field":"price"
}
}
}
}
}
}
// 取各种颜色车的平均价格
@Test
public void aggTest2() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询创建者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//添加聚合条件
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("colors").field("color.keyword").
subAggregation(AggregationBuilders.avg("avgPrice").field("price"));
ssb.aggregation(aggregationBuilder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//取结果
Terms terms = search.getAggregations().get("colors");
//取颜色的聚合结果
for (Terms.Bucket bucket : terms.getBuckets()) {
Avg avgPrice = bucket.getAggregations().get("avgPrice");
//取嵌套在第一层结果中的平均价格
System.out.println(bucket.getKeyAsString() +" "+ avgPrice.getValue());
}
}
例三:每个颜色的汽车制造商的分布
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
},
"make": {
"terms": {
"field": "make"
}
}
}
}
}
}
//取每种颜色桶的平均价格和颜色桶中不同的制造商
@Test
public void aggTest3() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("colors").field("color.keyword").
subAggregation(AggregationBuilders.avg("avgPrice").field("price")).
subAggregation(AggregationBuilders.terms("whereMake").field("make.keyword"));
ssb.aggregation(aggregationBuilder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Terms colorTerm = search.getAggregations().get("colors");
for (Terms.Bucket bucket : colorTerm.getBuckets()) {
Avg avgPrice = bucket.getAggregations().get("avgPrice");
Terms makes = bucket.getAggregations().get("whereMake");
for (Terms.Bucket makesBucket : makes.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" "+avgPrice.getValue()+" "+makesBucket.getKeyAsString()+" "+makesBucket.getDocCount());
}
}
}
例四:不同颜色同中为每个汽车生成商计算最低和最高的价格
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": { "avg": { "field": "price" }
},
"make" : {
"terms" : {
"field" : "make"
},
"aggs" : {
"min_price" : { "min": { "field": "price"} },
"max_price" : { "max": { "field": "price"} }
}
}
}
}
}
}
//每种颜色桶的平均价格和 桶中不同的制造商 和 颜色桶中不同厂商的最高价格和最低价格
@Test
public void aggsTest() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("colors").field("color.keyword").
subAggregation(AggregationBuilders.avg("avgPrice").field("price")).
subAggregation(AggregationBuilders.terms("whereMake").field("make.keyword").
subAggregation(AggregationBuilders.min("minPrice").field("price")). //minPrice桶和maxPrice桶是嵌套在whereMake桶中的
subAggregation(AggregationBuilders.max("maxPrice").field("price")));
ssb.aggregation(aggregationBuilder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//获得颜色桶
Terms colorsTerm = search.getAggregations().get("colors");
//遍历颜色桶
for (Terms.Bucket bucket : colorsTerm.getBuckets()) {
Avg avgPrice = bucket.getAggregations().get("avgPrice");
//获取颜色桶中的whereMake桶
Terms makes = bucket.getAggregations().get("whereMake");
for (Terms.Bucket makesBucket : makes.getBuckets()) {
Min minPirce = makesBucket.getAggregations().get("minPrice");
Max maxPrice = makesBucket.getAggregations().get("maxPrice");
System.out.println(bucket.getKeyAsString()+" "+avgPrice.getValue()+" "+makesBucket.getKeyAsString()+
" "+makesBucket.getDocCount()+" maxPrice:"+maxPrice.getValue()+" minPrice:"+minPirce.getValue());
}
}
}
例五:每个月销售的车辆数
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "month",
"format": "yyyy-MM-dd",
"min_doc_count" : 0,
"extended_bounds" : {
"min" : "2014-01-01",
"max" : "2014-12-31"
}
}
}
}
}
//2014年1-12月每个月销售的车辆数
@Test
public void aggsTest5() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//设置时间区间
ExtendedBounds extendedBounds = new ExtendedBounds("2014-01-01", "2014-12-31");
DateHistogramAggregationBuilder aggregationBuilder = AggregationBuilders.dateHistogram("sales").field("sold").
calendarInterval(DateHistogramInterval.MONTH). //DateHistogramInterval.MONTH参数 设置时间间隔要求为每个月
format("yyyy-MM-dd").extendedBounds(extendedBounds); //时间格式转要求
ssb.aggregation(aggregationBuilder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
ParsedDateHistogram date = search.getAggregations().get("sales");
for (Histogram.Bucket bucket : date.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());
}
}
例六:按季度、每个汽车品牌计算销售总额,同时展示每部车的价格和每个季度的销售数量
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "quarter",
"format": "yyyy-MM-dd",
"min_doc_count" : 0,
"extended_bounds" : {
"min" : "2014-01-01",
"max" : "2014-12-31"
}
},
"aggs": {
"per_make_sum": {
"terms": {
"field": "make"
},
"aggs": {
"sum_price": {
"sum": { "field": "price" }
}
}
},
"total_sum": {
"sum": { "field": "price" }
}
}
}
}
}
//同时按季度、每个汽车品牌计算销售总额,同时展示每部车的价格和每个季度的销售数量
@Test
public void aggsTest6() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//设置时间区间
ExtendedBounds extendedBounds = new ExtendedBounds("2014-01-01", "2014-12-31");
DateHistogramAggregationBuilder aggregationBuilder = AggregationBuilders.dateHistogram("sales").field("sold").
calendarInterval(DateHistogramInterval.QUARTER). //DateHistogramInterval.MONTH参数 设置时间间隔要求为每个月
format("yyyy-MM-dd"). //时间格式转要求
extendedBounds(extendedBounds). // 以上为根据季度聚合的桶
subAggregation(AggregationBuilders.sum("totalPrice").field("price")). // 根据季度统计总销售额 被包含在季度桶中
subAggregation(AggregationBuilders.terms("makeSale").field("make.keyword"). // 根据季度桶 再次聚合 每个季度中厂商的桶
subAggregation(AggregationBuilders.terms("price").field("price"))); // 根据每季度厂商的桶 聚合 每部车的价格桶
ssb.aggregation(aggregationBuilder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
ParsedDateHistogram sales = search.getAggregations().get("sales"); //获取按季度统计的桶
for (Histogram.Bucket bucket : sales.getBuckets()) { //解析季度统计桶
Terms makeSale = bucket.getAggregations().get("makeSale"); //解析季度统计桶中聚合的各厂商桶
Sum totalPrice = bucket.getAggregations().get("totalPrice"); //解析按照季度统计的总销售额
for (Terms.Bucket totalPriceBucket : makeSale.getBuckets()) {
Terms price = totalPriceBucket.getAggregations().get("price"); //解析季度统计桶中聚合的各厂商桶中聚合的每部车的价格桶
for (Terms.Bucket priceBucket : price.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" 总价格:"+totalPrice.getValue()+
" 厂商:"+totalPriceBucket.getKeyAsString()+" "+priceBucket.getDocCount()+
" 价格:"+priceBucket.getKeyAsString());
}
}
}
}
范围限定的聚合
例七:福特已售车有多少种颜色
与例一不同的是 需在福特车品牌范围内获取不同颜色车的个数
GET /cars/transactions/_search
{
"query" : {
"match" : {
"make" : "ford"
}
},
"aggs" : {
"colors" : {
"terms" : {
"field" : "color"
}
}
}
}
@Test
public void aagsTest() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest();
//构建查询创建者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//添加聚合条件
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.
terms("popular_colors").//设置一个桶的名字 取结果的时候需要用到
field("color.keyword"); // 聚合的字段 color类型为text 取类型为keyword的子字段color.keyword
ssb.aggregation(aggregationBuilder);
//封装查询条件范围
ssb.query(QueryBuilders.matchQuery("make","ford"));
request.indices("cars");
request.source(ssb);
//执行查询返回查询响应结果
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
//取结果
Terms aggs = search.getAggregations().get("popular_colors");
for (Terms.Bucket bucket : aggs.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());
}
}
例八 全局桶的使用
: 福特汽车与所有汽车平均售价的比较
全局桶包含所有的文档,它无视查询的范围。
GET /cars/transactions/_search
{
"size" : 0,
"query" : {
"match" : {
"make" : "ford"
}
},
"aggs" : {
"single_avg_price": {
"avg" : { "field" : "price" }
},
"all": {
"global" : {},
"aggs" : {
"avg_price": {
"avg" : { "field" : "price" }
}
}
}
}
}
// 全局桶的使用: 福特汽车与所有汽车平均售价的比较
@Test
public void aggTest7() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("avgPrice").field("price");
GlobalAggregationBuilder globalAggregationBuilder = new GlobalAggregationBuilder("all").
subAggregation(AggregationBuilders.avg("allAVGPrice").field("price"));
ssb.aggregation(avgAggregationBuilder);
ssb.aggregation(globalAggregationBuilder);
ssb.query(QueryBuilders.matchQuery("make","ford"));
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Avg avgPrice = search.getAggregations().get("avgPrice");
//获取全局聚合桶
Global allPrice = search.getAggregations().get("all");
//根据全局聚合桶获取平均价格桶
Avg allAVGPrice = allPrice.getAggregations().get("allAVGPrice");
System.out.println("福特车平均价:"+avgPrice.getValue()+
" 所有汽车平均价:"+allAVGPrice.getValue());
}
例九:1000美元以上所有车的平均价格
使用filter过滤器会忽略评分,并提升查询效率
//1000美元 以上的车的 平均价格
@Test
public void aggTest8() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
AvgAggregationBuilder avgPriceBuilder = AggregationBuilders.avg("avgPrice").field("price");
ssb.aggregation(avgPriceBuilder);
ssb.query(QueryBuilders.constantScoreQuery(
QueryBuilders.rangeQuery("price").gte(10000f)
));
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Avg avgPrice = search.getAggregations().get("avgPrice");
System.out.println(avgPrice.getValue());
}
例十 过滤桶
:对结果进行过滤
14年11月份的平均销售额
GET /cars/transactions/_search
{
"query":{
"match": {
"make": "honda"
}
},
"aggs":{
"recent_sales": {
"filter": {
"range": {
"sold": {
"from": "2014-11-01",
"to": "2014-11-30"
}
}
},
"aggs": {
"average_price":{
"avg": {
"field": "price"
}
}
}
}
}
}
结果可以看到他是将所有的honda品牌的结果查询出来 ,只是对聚合结果进行过滤
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.9444616,
"hits" : [
{
"_index" : "cars",
"_type" : "transactions",
"_id" : "_4QSSHgBiVHg5JEIPFIi",
"_score" : 0.9444616,
"_source" : {
"price" : 10000,
"color" : "red",
"make" : "honda",
"sold" : "2014-10-28"
}
},
{
"_index" : "cars",
"_type" : "transactions",
"_id" : "AIQSSHgBiVHg5JEIPFMj",
"_score" : 0.9444616,
"_source" : {
"price" : 20000,
"color" : "red",
"make" : "honda",
"sold" : "2014-11-05"
}
},
{
"_index" : "cars",
"_type" : "transactions",
"_id" : "BIQSSHgBiVHg5JEIPFMj",
"_score" : 0.9444616,
"_source" : {
"price" : 20000,
"color" : "red",
"make" : "honda",
"sold" : "2014-11-05"
}
}
]
},
"aggregations" : {
"recent_sales" : {
"doc_count" : 2,
"average_price" : {
"value" : 20000.0
}
}
}
}
// 过滤桶:对聚合结果进行过滤 14年11月份的平均销售额
@Test
public void aggTest9() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
FilterAggregationBuilder filterAggregationBuilder = AggregationBuilders.filter("lastMonthSales",
QueryBuilders.rangeQuery("sold").from("2014-11-01").to("2014-12-01")).
subAggregation(AggregationBuilders.avg("lastMonthAvgPrice").field("price"));
ssb.aggregation(filterAggregationBuilder);
ssb.query(QueryBuilders.matchQuery("make","honda"));
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Filter filter = search.getAggregations().get("lastMonthSales");
Avg avg = filter.getAggregations().get("lastMonthAvgPrice");
System.out.println(avg.getValue());
}
例十一 后过滤器
:只过滤搜索结果,不过滤聚合结果 post_filter
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_post_filter.html
查询福特品牌中不同的颜色以及车辆数,查询结果中只显示绿色福特,但聚合结果全部显示
与过滤桶的效果相反
//后过滤器:只过滤搜索结果,不过滤聚合结果 post_filter
//查询福特品牌中不同的颜色以及车辆数,查询结果中只显示绿色福特,但聚合结果全部显示
@Test
public void aggsTest10() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//聚合
TermsAggregationBuilder allColors = AggregationBuilders.terms("all_colors").field("color.keyword");
//查询
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("make", "ford");
//封装条件
ssb.aggregation(allColors);
ssb.query(matchQueryBuilder);
ssb.postFilter(QueryBuilders.termQuery("color","green"));
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Terms colorsTerms = search.getAggregations().get("all_colors");
for (Terms.Bucket bucket : colorsTerms.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" 车辆数"+bucket.getDocCount());
}
}
使用条件: 当需要对搜索结果和聚合结果做不同的过滤时,你才应该使用 post_filter
post_filter
的特性是在查询 之后 执行,任何过滤对性能带来的好处(比如缓存)都会完全失去。
- 在
filter
过滤中的non-scoring
查询,同时影响搜索结果和聚合结果。 filter
桶影响聚合。post_filter
只影响搜索结果。
多桶排序
例十二:颜色桶按个数升序排序
GET /cars/transactions/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color",
"order": {
"_count" : "asc"
}
}
}
}
}
关键字_count是按照doc_count值排序的。
order参数可以设置一以下内容:
_count 按文档个数排序。对terms、histogram、date_histogram有效。
_term 按词项的字符串的字母顺序排序,只在terms内使用。
key 按每个桶的键值数值排序(理论上与 _term类似),只在histogram和date_histogram 内使用。
//颜色桶按个数升序排序
@Test
public void aggTest11() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
TermsAggregationBuilder colors = AggregationBuilders.terms("colors").field("color.keyword").order(BucketOrder.count(true));
ssb.aggregation(colors);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Terms colorsTerms = search.getAggregations().get("colors");
for (Terms.Bucket bucket : colorsTerms.getBuckets()) {
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());
}
}
例十三:颜色桶获取每个桶的平均价并按照平均价排序
GET /cars/transactions/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color",
"order": {
"avg_price" : "asc"
}
},
"aggs": {
"avg_price": {
"avg": {"field": "price"}
}
}
}
}
}
//颜色桶获取每个桶的平均价并按照平均价排序
@Test
public void aggTest12() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
TermsAggregationBuilder colors =
AggregationBuilders.terms("colors").field("color.keyword").order(BucketOrder.aggregation("avgPrice",true)). //order参数中设置平均价桶的名字即可
subAggregation(AggregationBuilders.avg("avgPrice").field("price"));
ssb.aggregation(colors);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Terms terms = search.getAggregations().get("colors");
for (Terms.Bucket bucket : terms.getBuckets()) {
Avg avgPrice = bucket.getAggregations().get("avgPrice");
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount()+" 均价"+avgPrice.getValue());
}
}
例十四: extended_stats
度量
extended_stats
参数中有许多值 如sum、avg、min、max等等,如果需要用来排序可以直接使用 . 的方式设置
GET /cars/transactions/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color",
"order": {
"stats.variance" : "asc"
}
},
"aggs": {
"stats": {
"extended_stats": {"field": "price"}
}
}
}
}
}
部分结果
//extended_stats 度量
@Test
public void aggTest13() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
TermsAggregationBuilder colors =
AggregationBuilders.terms("colors").field("color.keyword").order(BucketOrder.aggregation("stats.variance",false)).
subAggregation(AggregationBuilders.extendedStats("stats").field("price"));
ssb.aggregation(colors);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Terms terms = search.getAggregations().get("colors");
for (Terms.Bucket bucket : terms.getBuckets()) {
ExtendedStats stats = bucket.getAggregations().get("stats");
System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount()+" "+stats.getVarianceAsString()); //由于extendedStats有很多值,这里只列出排序的那个值
}
}
统计去重后的数量: cardinality
例十五:统计共有多少种颜色
GET /cars/transactions/_search
{
"size" : 0,
"aggs" : {
"distinct_colors" : {
"cardinality" : {
"field" : "color"
}
}
}
}
//统计几种颜色的车辆
@Test
public void aggTest14() throws IOException {
//创建查询请求
SearchRequest request = new SearchRequest("cars");
//构建查询建造者
SearchSourceBuilder ssb = new SearchSourceBuilder();
//去重聚合
CardinalityAggregationBuilder builder = AggregationBuilders.cardinality("distinct_color").field("color.keyword");
ssb.aggregation(builder);
request.source(ssb);
SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
Cardinality cardinality = search.getAggregations().get("distinct_color");
System.out.println(cardinality.getValue());
}
经验总结:看ES查询代码的聚合结构 即可构建出java代码。哪些桶嵌套在哪个桶内,重要的是搞清楚ES代码的结构!!!
欢迎各位到评论区交流,有什么不足和问题请多多指正哈!