温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何解决ES深度分页问题

发布时间:2021-10-12 11:19:58 来源:亿速云 阅读:869 作者:iii 栏目:编程语言

这篇文章主要介绍“如何解决ES深度分页问题”,在日常操作中,相信很多人在如何解决ES深度分页问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何解决ES深度分页问题”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

ES深度分页问题:

ES 默认采用的分页方式是 from+ size 的形式,类似于MySQL的分页offset+limit。当请求数据量比较大时,Elasticsearch会对分页做出限制,因为此时性能消耗会很大。例如查询1000条数据,假设我们有5个分片,那么每个shard都需要返回1000条数据给 coordinating node,而 coordinating node 需要接收 5*1000 条数据,进行排序后返回1000条数据给客户端。即使每条数据只有 _doc _id 和 _score,这数据量也很大了,如果请请求量很大的情况下,很容易造成ES的OOM。ES中有个设置index.max_result_window ,默认是10000条数据,如果分页的数据超过第1万条,就拒绝返回结果了。如果集群配置比较好,查询请求量不是特别大,可以适当的放大这个参数。

解决方案:

1:使用scroll遍历

scroll 分为初始化和遍历两步,初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照,在遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果。因此,scroll 并不适合用来做实时搜索,而更适用于后台批处理任务等

API说明:

1)初始化

POST /book/_search?scroll=1m&size=2
{
"query": { "match_all": {}}
}
  1. 遍历

GET /_search/scroll
{
"scroll": "1m",
"scroll_id" : "步骤1中查询出来的值"
}

使用java RestHighLevelClient代码参考如下:

@Autowired
private RestHighLevelClient restHighLevelClient;

public Result<GoodsDTo>  scrollSearch(...查询参数){
     BoolQueryBuilder queryBuilder.te = QueryBuilders.boolQuery();
     //添加自己的搜索条件....
     queryBuilder.must(QueryBuilders.termQuery("type", "商品所属分类);
     queryBuilder.must(QueryBuilders.matchQuery("name", "商品名称");
     //搜索
     SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
     searchSourceBuilder.query(queryBuilder);
     //排序
     searchSourceBuilder.sort(SortBuilders.fieldSort("order").order(SortOrder.DESC));
     //搜索结果
     SearchResponse searchResponse = null;
     //根据实际情况,判断是多次调用还是一次while遍历查询全部
  	if (StringUtils.isBlank("scrollId")) {
            //首屏
            searchSourceBuilder.size("每次查询的条数");
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.indices("索引名").source(searchSourceBuilder);
            searchRequest.scroll(new Scroll(TimeValue.timeValueMinutes(scrollKeepAliveTime)));
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
     } else {
            //后续根据上次的id滚动
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest("scrollId");
            searchScrollRequest.scroll(new Scroll(TimeValue.timeValueMinutes(scrollKeepAliveTime)));
            searchResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
     }
        
     SearchHit[] hits = searchResponse.getHits().getHits();
     //根据业务需求,处理搜索结果
     GoodsDTO result= handleSearchData(hits);
     //scrollId,往下滚动需要使用
     String scrollId = searchResponse.getScrollId();
     return Result.succcess(result);
}

2:使用search after

满足实时获取下一页的文档信息,search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改,这些变更也会实时的反映到游标上,这种方式是在es-5.X之后才提供的。为了找到每一页最后一条数据,每个文档的排序字段必须有一个全局唯一值使用 _id 就可以了。

API说明:

GET /book/_search
{
    "query": {"match_all": {}},
    "size": 2,
    "sort": [{"_id": "desc"}]
}
GET /book/_search
{
    "query": {"match_all": {}},
    "size": 2,
    "search_after": [3],
    "sort": [{"_id": "desc"}]
}

下一页的数据依赖上一页的最后一条的信息 所以不能跳页

使用java RestHighLevelClient代码参考如下:

@Autowired
private RestHighLevelClient restHighLevelClient;

public Result<GoodsDTo>  searchAfter(...查询参数){
        SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(...搜索条件);
        searchSourceBuilder.size(1000);
        searchSourceBuilder.sort("_id", SortOrder.ASC);
        searchSourceBuilder.searchAfter("上一页最后一条数据的id");
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
         //根据业务需求,处理搜索结果
         GoodsDTO result= handleSearchData(hits);
         return Result.succcess(result);
}

到此,关于“如何解决ES深度分页问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI