ElasticSearch 聚合查询百分比

时间:2023-03-09 18:34:04
ElasticSearch  聚合查询百分比

这里用的是es5.6.9

bucket_script :它执行一个脚本,该脚本可以对多桶聚合中的指定度量执行每桶计算,指定的度量标准必须为数字,并且脚本必须返回数值。

官方语法

https://www.elastic.co/guide/en/elasticsearch/reference/master/search-aggregations-pipeline-bucket-script-aggregation.html

{
"bucket_script": {
"buckets_path": {
"my_var1": "the_sum",
"my_var2": "the_value_count"
},
"script": "params.my_var1 / params.my_var2"
}
}

给的一个例子

算出t-shirts卖出的钱占总钱数的百分比
POST /sales/_search
{
"size": ,
"aggs" : {
"sales_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_sales": {
"sum": {
"field": "price"
}
},
"t-shirts": {
"filter": {
"term": {
"type": "t-shirt"
}
},
"aggs": {
"sales": {
"sum": {
"field": "price"
}
}
}
},
"t-shirt-percentage": {
"bucket_script": {
"buckets_path": {
"tShirtSales": "t-shirts>sales",
"totalSales": "total_sales"
},
"script": "params.tShirtSales / params.totalSales * 100"
}
}
}
}
}
}
script:聚合运行的脚本
buckets_path:脚本变量的映射及其与我们希望用于变量的桶的关联路径
format:格式以应用于此聚合的输出值
gap_policy:在数据中发现差距时应用的策略
其中"t-shirts"这个聚合里面又套了一层取值的聚合是因为buckets_path里引用的必须是一个值filter返回的不是一个值

也可以这样写
POST /sales/_search
{
"size": ,
"aggs" : {
"sales_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_sales": {
"sum": {
"field": "price"
}
},
"t-shirts": {
"filter": {
"term": {
"type": "t-shirt"
}
}
},
"t-shirt-percentage": {
"bucket_script": {
"buckets_path": {
"tShirtSales": "t-shirts>_count",
"totalSales": "total_sales"
},
"script": "params.tShirtSales / params.totalSales * 100"
}
}
}
}
}
}

在spring data 中使用 bucket_script 聚合

ValueCountAggregationBuilder valueCountAggregationBuilder=AggregationBuilders.count("聚合的名字:total_attendance").field("聚合的字段名");
FilterAggregationBuilder filterLate=AggregationBuilders
.filter("聚合的名字:filter_count",QueryBuilders.termQuery("term的字段名","过滤的字段值"));
Map<String,String> scriptParams=new HashMap<>();
lateScriptParams.put("total","total_attendance");
lateScriptParams.put("count","filter_count>_count");
BucketScriptPipelineAggregationBuilder script= PipelineAggregatorBuilders
.bucketScript("聚合的名字:result",scriptParams,new Script("params.count/params.total*100")).format("#.##");

然后就是把聚合放到查询里面了

TermsAggregationBuilder usersResultAggs= AggregationBuilders.terms("users_term").field("userId.keyword")
.subAggregation(result)
.subAggregation(filter_count)
.subAggregation(total);

取值

1.使用elasticsearchTemplate

elasticsearchTemplate.query(searchQuery, searchResponse -> {
Map<String,Aggregation> aggregationMap=searchResponse.getAggregations().asMap();
StringTerms stringTerms = (StringTerms)aggregationMap.get("取值的那个聚合的名字:users_term");         //取值
       return aggregationMap.get("取值的那个聚合的名字:result")).getValue()
   stringTerms.getBuckets().forEach(aggs->{
Map<String,Aggregation> subAggMap=aggs.getAggregations().asMap();
    //取百分比
    Double result=((InternalSimpleValue)subAggMap.get("notsigendScript")).getValue();
  });
  return 返回结果;
});