快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

如何解决ES深度分页问题

这篇文章主要介绍“如何解决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  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  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深度分页问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


分享文章:如何解决ES深度分页问题
地址分享:http://6mz.cn/article/jochdg.html

其他资讯