文章摘要(AI生成)
使用es做分页查询方式有三种from+ size 分页,如果数据量不大或者from、size不大的情况下,效率还是蛮高的。但是在深度分页的情况下,这种使用方式效率是非常低的,并发一旦过大,还有可能直接拖垮整个ElasticSearch的集群。scroll 分页通常不会用在客户端,因为每一个 scro
使用es做分页查询方式有三种
from+ size 分页,如果数据量不大或者from、size不大的情况下,效率还是蛮高的。但是在深度分页的情况下,这种使用方式效率是非常低的,并发一旦过大,还有可能直接拖垮整个ElasticSearch的集群。
scroll 分页通常不会用在客户端,因为每一个 scroll_id 都会占用大量的资源,一般是后台用于全量读取数据使用
search_after通过维护一个实时游标来避免scroll的缺点,它可以用于实时请求和高并发场景,一般用于客户端的分页查询
大体而言就是在这三种分页方式中,from + size不适合数据量很大的场景,scroll不适合实时场景,而search after在es5.x版本之后应运而生,较好的解决了这个问题
由于项目中只是做简单列表页展示,所以暂时使用浅分页这种from+size的分页方式,而在使用这种分页方式时,需要注意以下几个点:
1、使用collapse函数直接获取列表页所需字段的去重结果
2、使用aggregation函数可以根据指定字段进行聚合求出我们去重结果的总数量,以便分页
3、使用分片索引时,最好指定默认的时间范围,限制输出结果(10000条以内)以便以命中最少索引分区,使性能达到最佳
tips:
与查询用must,或查询用should(minimumShouldMatch指定最少条件匹配数),范围查询用range
代码示例如下:
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//设置根据哪个字段进行排序查询
String[] fields = {"uuid","column1","column2","column3","column4", "create_time"};
sourceBuilder.fetchSource(fields, null);
sourceBuilder.aggregation(AggregationBuilders.cardinality("total_size").field("uuid"));
sourceBuilder.collapse(new CollapseBuilder("uuid"));
sourceBuilder.sort(new FieldSortBuilder("order_create_time").order(SortOrder.DESC));
BoolQueryBuilder builder = QueryBuilders.boolQuery();
if(!StringUtils.isEmpty(column1)){
builder.must(QueryBuilders.termsQuery("column1", recordNo));
}
if(StringUtils.isEmpty(column1)){
endTime = new DateTime(startTime).plusDays(1).toDate();
}
if(!StringUtils.isEmpty(column2)){
builder.must(QueryBuilders.termsQuery("column2", bizLine));
}
builder.must(QueryBuilders.termsQuery("column3", String.valueOf(SplitOrderTypeEnum.SPLIT.getCode())));
builder.must(QueryBuilders.termsQuery("is_delete", String.valueOf(DeleteStatusEnum.NO.getCode())));
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("create_time");
rangeQueryBuilder.from(startTime.getTime());
rangeQueryBuilder.to(endTime.getTime());
builder.must(rangeQueryBuilder);
//设置超时时间
sourceBuilder.timeout(new TimeValue(120, TimeUnit.SECONDS));
//设置是否按匹配度排序
sourceBuilder.explain(true);
//加载查询条件
sourceBuilder.query(queryBuilder);
//设置分页
sourceBuilder.from((startPage - 1) * pageSize).size(pageSize);
//根据时间范围截取索引
List<String> indexList = getIndexListByDate(startTime, endTime);
//获取es中的索引分片
List<String> clientIndexList = esClient.getIndexListFromClient(getIndex());
//取索引交集
List<String> result = indexList.stream().filter(clientIndexList::contains).collect(Collectors.toList());
SearchRequest request = new SearchRequest(indexes);
request.source(sourceBuilder);
评论区