原创Java使用RestHighLevelClient操作ElasticSearch,实现多字段Group by并将结果进行count排序

Posted DCTANT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创Java使用RestHighLevelClient操作ElasticSearch,实现多字段Group by并将结果进行count排序相关的知识,希望对你有一定的参考价值。

前言

之前写过一篇使用RestHighLevelClient进行多字段group by的(【原创】ElasticSearch使用Java代码group by多个字段查询统计数量_DCTANT的博客-CSDN博客_elasticsearch分组统计 java),其实那篇并不完美,最佳的group by方法应该用script,而不是像之前那篇博客一样去递归求和,虽然也不是不行,但是这个毕竟太暴力了,效率也不高。

直接上代码:

初始化RestHighLevelClient我这边为了节省篇幅先跳过了,直接上核心:

SearchRequest searchRequest = new SearchRequest(index);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

//为了保持顺序,使用LinkedHashMap,防止进入map后变成乱序排列
LinkedHashMap<String, Long> nameCountMap = new LinkedHashMap<>();
//group by后再order by
BucketOrder bucketOrder = BucketOrder.count(false); //这里的count方法中true表示升序排列,false代表降序排列
AggregationBuilder aggregationBuilder = AggregationBuilders.terms("$分组名") //分组名可以随便填,但是必须和后面aggregations.get("$分组名");里面填的分组名保持一致,否则会返回null,导致后续空指针异常
                                                           .script(new Script("doc['$字段1'].value+'@@'+doc['$字段2'].value+'@@'+doc['$字段3'].value+'@@'+doc['$字段4'].value")) //相当于group by 4个字段,其中的@@是字段间的分隔符,最后ES返回的结果是这样的$字段1@@$字段2@@$字段3@@$字段4
                                                           .size(20) //聚合返回20个值(不传默认返回10个值)
                                                           .order(bucketOrder); //将上方的排序填入,让ES进行排序
sourceBuilder.aggregation(aggregationBuilder); //填入分组信息
searchRequest.source(sourceBuilder);
try 
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    Aggregations aggregations = searchResponse.getAggregations();
    Terms terms = aggregations.get("$分组名"); //填入上方terms()中相同的分组名
    for (Terms.Bucket bucket : terms.getBuckets()) 
        String key = bucket.getKeyAsString(); //这里的key值是这样的:$字段1@@$字段2@@$字段3@@$字段4
        long count = bucket.getDocCount(); //group by后聚合统计出来的数量
        String[] split = key.split("@@"); //切开作为分隔符的@@,取里面需要的字段放入nameCountMap就行了
        nameCountMap.put(split[0], count); //假设取第0个字段作为key
    
 catch (IOException e) 
    e.printStackTrace();

// todo 处理剩下的业务逻辑

看一下注释应该就能懂了,相当于ES的查询为:


    "aggs":
        "myStatistic":
            "terms":
                "script":
                    "inline":"doc['字段1'].value+'@@'+doc['字段2'].value+'@@'+doc['字段3'].value+'@@'+doc['字段4'].value"
                ,
                "size":20,
                "order":
                    "_count":"desc"
                
            
     
        
    

参考链接:Elasticsearch入门 ,使用 script 做聚合查询 - 简书

如果script中的字段,其中有个值不存在则会报这个错:

ElasticSeach 采坑之A document doesn‘t have a value for a field! Use doc[<field>].size()==0 to check if_JAVA探索的博客-CSDN博客

解决方案如这个博客所示,我这边不再赘述

以上是关于原创Java使用RestHighLevelClient操作ElasticSearch,实现多字段Group by并将结果进行count排序的主要内容,如果未能解决你的问题,请参考以下文章

[原创]java WEB学习笔记36:Java Bean 概述,及在JSP 中的使用,原理

原创 | 不了解这12个语法糖,别说你会Java!

原创使用Java进行Clob转String字符串

原创Java使用RestHighLevelClient操作ElasticSearch,实现多字段Group by并将结果进行count排序

原创Java使用RestHighLevelClient操作ElasticSearch,实现多字段Group by并将结果进行count排序

java---03Java语言的基础构成(原创,请勿转载)