elasticSearch多字段聚合查询示例【基于java api】

一、使用环境

jdk:1.8

es:7.15.2

背景:实现类似select count(*),name,age from table_name group by name,age功能

二、查询代码:

使用Terms聚合查询,示例代码如下:

public  static Map<String,Map<String,Long>> groupByFields(String index, QueryBuilder query, String... fieldNames) throws IOException {
       SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
       TermsAggregationBuilder aggregationBuilder=null;
       for(String fieldName: fieldNames) {
           if(aggregationBuilder == null) {
               aggregationBuilder =  AggregationBuilders.terms(fieldName)
                       .field(fieldName);
           }else {
               aggregationBuilder.subAggregation(AggregationBuilders.terms(fieldName)
                       .field(fieldName));
           }
       }
       searchSourceBuilder.aggregation(aggregationBuilder);
       SearchRequest searchRequest = new SearchRequest(index);
       searchSourceBuilder.query(query);
       searchRequest.source(searchSourceBuilder);
       searchSourceBuilder.size(1);
       SearchResponse searchResponse = null;

       searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
       Aggregations aggregations = searchResponse.getAggregations();
       return   parseResult(aggregations, fieldNames);
   }
    private static Map<String,Map<String,Long>> parseResult(Aggregations aggregations,
                                                     String... fileds) {
        Map<String, Map<String,Long>> result = new HashMap<>();
        doParseResult(aggregations,result,"","",0, fileds);
        return result;
    }

    /**
     * 解析基于Terms聚合的聚合结果,按照字段进行解析。
     * 多个字段之间以|作为连接符
     * 列如以codeType + result两个字段聚合查询后。解析的结果如下:
     * 第一层map中key代表当前聚合的字段,value代表该字段所有的取值及取值统计值
     * 第二层map中key代表聚合字段的取值,value代表该值的出现的总次数
     * 返回结果如下:
     * {
     *     "codeType": {
     *         "2": 1285,
     *         "3": 101
     *     },
     *     "codeType|result": {
     *         "2|0": 624,
     *         "2|1": 661,
     *         "3|0": 83,
     *         "3|1": 18
     *     }
     * }
     * @param aggregations  聚合的原始结果
     * @param result 解析后的结果
     * @param preFiledName  上一层字段名
     * @param preFiledKey   上一层字段对应的值
     * @param index  目前使用的索引
     * @param filed  所有用来进行聚合的字段,需要要查询时传入的顺序保持一直
     * @return
     */
   private static void doParseResult(Aggregations aggregations, Map<String, Map<String,Long>> result,
                                           String preFiledName, String preFiledKey, int index,
                                           String... filed) {
        String filedName = filed[index];
        preFiledName = StringUtils.isEmpty(preFiledName) ? filedName  : preFiledName + "|" + filedName;
        Map<String, Long> fileNameMap =  result.getOrDefault(preFiledName, new HashMap<>());
        if (aggregations.get(filedName) instanceof Terms) {
            Terms terms = (Terms) aggregations.get(filedName);
            List<? extends Terms.Bucket> buckets = terms.getBuckets();
            preFiledKey = StringUtils.isEmpty(preFiledKey) ? "" : preFiledKey + "|";
            for (Terms.Bucket bucket : buckets) {
                fileNameMap.put(preFiledKey + bucket.getKeyAsString(), bucket.getDocCount());
                Aggregations bucketAggregations = bucket.getAggregations();
                if (bucketAggregations != null && index < filed.length - 1) {
                    doParseResult(bucketAggregations, result, preFiledName, preFiledKey + bucket.getKeyAsString(), index + 1, filed);
                }
            }
            result.put(preFiledName, fileNameMap);
        }
    }

你可能感兴趣的:(java,elasticsearch,开发语言)