這里用的是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": 0, "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": 0, "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 返回結果;
});