以下操作基于es6.8
第一种方式这种方式查询出来的数据不是扁平化的,而是一层套一层的,比如字段一套字段二。
GET 索引name/索引type/_search
{
"size": 0,
"aggregations": {
"字段一的结果命名": {
"terms": {
"field": "要group的字段"
},
"aggregations": {
"字段二的结果命名": {
"terms": {
"field": "要group的字段"
}
}
}
}
}
}
结果,one下面的buckets里面是two,每个two下面有自己的bukets,就是two的值和count。
java代码实现 public void demo1(RestHighLevelClient client) {
// group
TermsAggregationBuilder oneBuilder = AggregationBuilders.terms("one").field("flowCode.keyword");
TermsAggregationBuilder twoBuilder = AggregationBuilders.terms("two").field("stepExecuteId");
oneBuilder.subAggregation(twoBuilder);
// search
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.aggregation(oneBuilder);
// request
SearchRequest searchRequest = new SearchRequest("index");
searchRequest.types("type");
searchRequest.source(searchSourceBuilder);
try {
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
Terms oneTerm = (Terms) response.getAggregations().asMap().get("one");
for (Terms.Bucket bucket : oneTerm.getBuckets()) {
System.out.println("one下面的" + bucket.getKey() + ", count是: " + bucket.getDocCount());
Terms twoTerm = (Terms) bucket.getAggregations().asMap().get("two");
for (Terms.Bucket twoTermBucket : twoTerm.getBuckets()) {
System.out.println("two下面的" + twoTermBucket.getKey() + ", count是: " + twoTermBucket.getDocCount());
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
封装
封装一个通用的聚合查询并映射到java类中
package com.es.agg.demo; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class App2第二种方式{ private RestHighLevelClient client; public List group(String index, String type, String resultKey, BoolQueryBuilder queryBuilder, Class clazz, String... groupKeys) { TermsAggregationBuilder firstBuilder = null; TermsAggregationBuilder topAggregationBuilder = null; for (String groupKey : groupKeys) { TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms(groupKey).field(groupKey); if (topAggregationBuilder != null) { topAggregationBuilder.subAggregation(aggregationBuilder); } else { firstBuilder = aggregationBuilder; } topAggregationBuilder = aggregationBuilder; } SearchResponse response = this.group(index, type, queryBuilder, firstBuilder); List finishModels = new ArrayList<>(); Terms terms = (Terms) response.getAggregations().getAsMap().get(groupKeys[0]); this.buildEsModel(groupKeys, resultKey, terms, null, 0, finishModels); return finishModels.stream().map(item -> item.build(clazz)).collect(Collectors.toList()); } private void buildEsModel(String[] groupKeys, String resultKey, Terms terms, EsModel topEsModel, int level, List finishModels) { if (level == (groupKeys.length - 1)) { if (terms != null && terms.getBuckets() != null && !terms.getBuckets().isEmpty()) { for (Terms.Bucket bucket : terms.getBuckets()) { EsModel parentEsModel = new EsModel(groupKeys[level], bucket.getKey().toString(), topEsModel); EsModel childEsModel = new EsModel(resultKey, bucket.getDocCount(), parentEsModel); finishModels.add(childEsModel); } } } else { if (terms != null && terms.getBuckets() != null && !terms.getBuckets().isEmpty()) { for (Terms.Bucket bucket : terms.getBuckets()) { EsModel esModel = new EsModel(groupKeys[level], bucket.getKey().toString(), topEsModel); Terms childTerms = (Terms) bucket.getAggregations().getAsMap().get(groupKeys[level + 1]); buildEsModel(groupKeys, resultKey, childTerms, esModel, level + 1, finishModels); } } else { return; } } } public SearchResponse group(String index, String type, BoolQueryBuilder queryBuilder, TermsAggregationBuilder aggregationBuilder) { // 搜索源构建对象 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(queryBuilder); searchSourceBuilder.aggregation(aggregationBuilder); searchSourceBuilder.size(0); // 基础设置 SearchRequest searchRequest = new SearchRequest(index); searchRequest.types(type); searchRequest.source(searchSourceBuilder); try { return client.search(searchRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return null; } }
这种方式查出来的数据更扁平化,容易被接受
GET 索引名称/索引类型/_search
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"result": {
"terms": {
"script": {
"inline": "doc['字段1'].value +'分隔符'+ doc['字段2'].value "
}
}
}
}
}
可以看到,这次的数据很扁平化,只是中间有了分隔符,读取数据的时候 需要自己处理
java代码实现 public void demo2(RestHighLevelClient client) {
// script
script script = new script(scriptType.INLINE, "groovy", "doc['flowCode.keyword'].value+'-split-'+doc['stepExecuteId'].value", new HashMap<>());
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("result").script(script);
// search
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.aggregation(aggregationBuilder);
// request
SearchRequest searchRequest = new SearchRequest("index");
searchRequest.types("type");
searchRequest.source(searchSourceBuilder);
try {
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
Terms oneTerm = (Terms) response.getAggregations().asMap().get("result");
for (Terms.Bucket bucket : oneTerm.getBuckets()) {
// 此处自己split分隔处理
System.out.println(bucket.getKey().toString());
System.out.println(bucket.getDocCount());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
代码地址: https://github.com/qiaomengnan16/es-agg-demo



