Elasticsearch | es_分组-分页-TransportClient实现

本文介绍如何在Elasticsearch中使用TransportClient进行数据分组(group)操作,并实现手动分页与排序功能。详细解释了group操作后需手动设置分页及size参数的原因,以及在不同排序方式下如何截取对应范围的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说在前面:

Elasticsearch Java API 有四种实现方式:分别是 TransportClient、RestClient、Jest、Spring Data Elasticsearch。
本文使用第一种方式,也就是 TransportClient 的方式进行实现。想要了解其他三种的方式可以看一下这篇文章:https://blog.youkuaiyun.com/qq_33314107/article/details/80725913

总结:

1、group 之后不能自动分页,需要手动设置;

2、size 需要指定,否则会出错。


group 之后分页、排序实现

需要手动截取分页对应范围内的数据。

比如:这里

倒序,获取到数据集的第 (currentPage-1) * limit 到 currentPage * limit 条记录;

升序,获取到数据集的 第 buckets.size() - (currentPage - 1) * limit 到 buckets.size() - currentPage * limit 条记录。

// 获取到 response 之后
Aggregations aggregations = response.getAggregations();
Terms carids =  aggregations.get("group_car_bayId");
List<? extends Terms.Bucket> buckets =  carids.getBuckets();
List<carBean> listCarTgs = new ArrayList<>();
carBean carBean ;
// buckets 全部数据,分页就是取固定位置的 limit 条数据
// 默认按照统计之后的数量倒序, 如果要正序,则第一页从最后一条开始取
if(buckets.size()>0) {
    int i=0;
    if("desc".equalsIgnoreCase(order)) {// 倒序
        for(Terms.Bucket bucket : buckets){
            if(i++<(currentPage-1) * limit){
                continue;
            }
            if (i > currentPage * limit) {
                break;
            }
            carBean = new carBean();
            carBean.setPassTimes((int)bucket.getDocCount());
            carBean.setBayId(bucket.getKeyAsString().split("_")[2]);
            carBean.setPlateNumber(bucket.getKeyAsString().split("_")[0]);
            carBean.setPlateType(bucket.getKeyAsString().split("_")[1]);
            listCarTgs.add(carBean);
        }
    }else if("asc".equalsIgnoreCase(order)) {// 升序
        for(i = buckets.size() - 1; i >= 0; i--){
            if(i < buckets.size() - currentPage * limit){
                break;
            }
            if(i > buckets.size() - (currentPage - 1) * limit) continue;;
            carBean = new carBean();
            carBean.setPassTimes((int)buckets.get(i).getDocCount());
            carBean.setBayId(buckets.get(i).getKeyAsString().split("_")[2]);
            carBean.setPlateNumber(buckets.get(i).getKeyAsString().split("_")[0]);
            carBean.setPlateType(buckets.get(i).getKeyAsString().split("_")[1]);
            listCarTgs.add(carBean);
        }
    }
}

单个 group

注意:需要设置 size

TermsAggregationBuilder tb=  AggregationBuilders.terms("group_bayId").field("bay_id").size(Integer.MAX_VALUE);

多个 group

以脚本的形式

TermsAggregationBuilder tb=  AggregationBuilders.terms("group_carId").script(new Script("doc['plateNumber'].value+'_'+doc['plateType'].value"));
            tb.subAggregation(AggregationBuilders.topHits("max_time").sort("reportTime", SortOrder.DESC).size(1));

再比如:三个 group

BoolQueryBuilder filter = QueryBuilders.boolQuery();
if (carList != null && carList.size() >0) {
    filter.must(QueryBuilders.termsQuery("car_plate_number", carList.stream().map(SimpleCar:: getPlateNumber).collect(Collectors.toList())));
}
if (startTime != null && endTime != null) {
    filter.filter(QueryBuilders.rangeQuery("timestamp").gt(startTime.getTime()).lt(endTime.getTime()));
} else if (startTime != null) {
    filter.filter(QueryBuilders.rangeQuery("timestamp").gt(startTime.getTime()));
} else if (endTime != null) {
    filter.filter(QueryBuilders.rangeQuery("timestamp").lt(endTime.getTime()));
}
FieldSortBuilder sort = SortBuilders.fieldSort("transit_times").order("asc".equalsIgnoreCase(order)?SortOrder.ASC:SortOrder.DESC);
TermsAggregationBuilder termsAggregationBuilder =  AggregationBuilders.terms("group_car_bayId")
        .script(new Script("doc['car_plate_number'].value+'_'+doc['car_plate_type'].value + '_' +doc['bay_id'].value")).size(Integer.MAX_VALUE);
SearchResponse response = search(filter, sort, termsAggregationBuilder, elasticsearchProperties.getTgsIndex(), elasticsearchProperties.getTgsType(),
        (currentPage-1) * limit, 0);
Aggregations aggregations = response.getAggregations();

例子2:

TermsAggregationBuilder tb=  AggregationBuilders.terms("group_bayId").field("bay_id").size(Integer.MAX_VALUE);
    tb.order(BucketOrder.count(false));

在这里插入图片描述

实现 ES 聚合分页,可以使用 ElasticsearchJava API 来编写代码。下面是一个简单的示例: ```java import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.sum.Sum; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.transport.client.PreBuiltTransportClient; import java.net.InetAddress; import java.util.List; import java.util.Map; public class AggregationPaginationExample { public static void main(String[] args) throws Exception { TransportClient client = new PreBuiltTransportClient(Settings.EMPTY) .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)); int pageSize = 5; int pageNumber = 1; SearchResponse response = client.prepareSearch("my_index") .setQuery(QueryBuilders.matchAllQuery()) .addAggregation( AggregationBuilders.terms("my_terms_agg") .field("my_field") .subAggregation(AggregationBuilders.sum("my_sum_agg").field("my_other_field")) .order(Terms.Order.aggregation("my_sum_agg", false)) .size(pageSize) .from((pageNumber - 1) * pageSize) ) .setSize(0) .get(); Terms termsAgg = response.getAggregations().get("my_terms_agg"); for (Terms.Bucket bucket : termsAgg.getBuckets()) { String key = bucket.getKeyAsString(); long docCount = bucket.getDocCount(); Sum sumAgg = bucket.getAggregations().get("my_sum_agg"); double sumValue = sumAgg.getValue(); System.out.println(key + ": " + docCount + " documents, sum = " + sumValue); } client.close(); } } ``` 这个示例使用了 ElasticsearchJava API,查询一个名为 `my_index` 的索引,按照 `my_field` 字段进行分组,并计算每组中 `my_other_field` 字段的总和。然后按照总和排序,并使用分页参数进行分页。最后打印出每个分组的结果。 需要注意的是,聚合分页实现方式与普通的分页略有不同,具体可以参考上面的代码示例。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伍六七AI编程

你猜你给我1分我要不要

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值