欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

ELASTIC SEARCH分页查询探究
(last modified Aug 2, 2022, 4:59 PM )
by
侧边栏壁纸
  • 累计撰写 186 篇文章
  • 累计创建 65 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

ELASTIC SEARCH分页查询探究

橙序员
2022-07-19 / 0 评论 / 0 点赞 / 724 阅读 / 719 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(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);
0

评论区