es的深度分页查询

本文介绍了在Elasticsearch中如何处理搜索结果超过10000条的场景,通过深度分页的代码示例展示了如何获取全部数据。在搜索过程中,当文档总数大于默认限制时,使用searchAfter方法进行分页,循环执行搜索直到所有数据都被检索出来。这是一个实用的方法来解决ES的分页问题。

  在使用es的过程中,有些时候会遇到搜索全部数据的场景,众所周知es最大的搜索的数量就是10000,那么碰到总数大于10000时,我们就要用到深度分页这个功能。

  下面是一段浅写的深度分页的代码,供日后自己用

/**
 *深度分页搜索
 *
 */
public void deepSearch(){
    SearchRequst searchRequst = new SearchRequst("索引名称");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //创建构造条件
    searchSourceBuilder.source(searchSourceBuilder);

    //执行搜索
    Long total = 0L;
    try{
        //esMapper其实就是封装的restHighLevelClient
        SearchResponse searchResponse = esMapper.search(searchRequest,RequestOptions.DEFAULT);
        if(searchResponse == null
                || searchResponse.getHits().getHits() == null
                || searchResponse.getHits().getHits().length == 0){
            log.info("深度分页搜索结果为空");
            return null;
        }
        SearchHit[] searchHits = searchResponse.gitHit().git();
        while(searchHits.length > 0){
            total += searchHits.length;
            searchSourceBuilder.searchAfter(searchHits[searchHits.length -                     1].getSortValues());
            searchResponse = esMapper.search(searchRequest,RequestOptions.DEFAULT);
            if(searchResponse == null
                || searchResponse.getHits().getHits() == null
                || searchResponse.getHits().getHits().length == 0){
            log.info("深度分页搜索结束循环!");
            break;
            }
            searchHits = searchResponse.getHits().getHits();
        }
    }catch(IOException e){
        log.error("深度分页搜索发生异常");
    }
    log.info("深度分页搜索结束,召回的文档总数为:{}",total);
}

<think>嗯,用户想了解Elasticsearch深度分页查询Search_after,并且要求图文教程。首先,我得回忆一下Search_after的作用和适用场景。记得之前学的时候,Elasticsearch的分页有from+size的方式,但深度分页时性能会下降,特别是数据量大的时候。Search_after应该是解决这个问题的。 那Search_after的原理是什么呢?应该是基于上一页的排序值来获取下一页的数据,避免深度翻页时的性能损耗。不过需要基于唯一的排序字段,比如时间戳或者_id,否则可能会有重复。要确保排序字段的值是唯一的,否则分页可能会出错。 接下来,用户可能需要具体的步骤和示例。应该分步骤讲解,先讲前置条件,比如索引创建和数据准备,然后讲如何第一次查询,获取search_after的值,再讲如何用这个值进行下一页的查询。同时要注意,使用Search_after时必须指定排序,而且排序字段要唯一,否则分页可能不准确。 可能还需要对比一下Search_after和Scroll API的区别,Scroll适合大量数据导出,而Search_after适合实时分页。另外,用户可能想知道Search_after的优缺点,比如不能跳页,只能逐页翻,但性能更好。 图文教程的话,可能需要插入一些示例代码和结果截图。虽然现在不能实际贴图,但可以用文字描述示例输出,比如第一次查询返回的数据和sort值,下一页查询使用search_after参数的情况。 还要注意用户可能遇到的常见问题,比如排序字段不唯一导致分页重复或遗漏,或者忘记添加排序条件。需要提醒用户确保排序字段的唯一性,比如使用_id作为第二排序字段。 最后,总结一下适用场景,比如移动端加载更多,或者需要深度分页但不需要跳页的情况。可能用户的实际应用场景是这样的,所以明确说明Search_after的适用性很重要。</think>Elasticsearch 深度分页查询 Search_after 图文教程(文字版) 一、为什么需要 Search_after? ![分页性能对比图] 传统分页(from+size)在深度分页时性能骤降,Search_after 通过游标机制实现高效深度分页,适合处理百万级数据的分页场景。 二、核心原理 1. 基于排序字段的值作为游标 2. 每次查询携带上一页最后一条的排序值 3. 避免全局排序,性能损耗稳定($O(1)$) 三、具体使用步骤 1. 前置条件:创建测试索引 ```json PUT /products { "mappings": { "properties": { "name": { "type": "text" }, "price": { "type": "double" }, "timestamp": { "type": "date" } } } } ``` 2. 首次查询(必须包含排序) ```json GET /products/_search { "size": 2, "sort": [ { "timestamp": "desc" }, { "_id": "asc" } // 确保排序唯一性 ] } ``` 响应示例: ```json { "hits": { "hits": [ { "_id": "1", "_source": { "name": "Phone", "price": 599.99 }, "sort": [1658800000000, "1"] }, { "_id": "2", "_source": { "name": "Laptop", "price": 1299.99 }, "sort": [1658700000000, "2"] } ] } } ``` 3. 后续查询使用 search_after ```json GET /products/_search { "size": 2, "sort": [ { "timestamp": "desc" }, { "_id": "asc" } ], "search_after": [1658700000000, "2"] // 使用上页最后记录的sort值 } ``` 四、注意事项(⚠️关键点) 1. 必须指定唯一性排序组合(推荐:业务字段 + _id) 2. 不能跳页查询,只能顺序翻页 3. 索引更新可能导致分页结果变化(实时性特征) 4. 需要客户端维护上下文状态 五、与 Scroll API 对比 | 特性 | Search_after | Scroll | |---------------------|------------------------|----------------------| | 实时性 | ✅ 实时 | ❌ 快照 | | 内存消耗 | 低 | 高 | | 适用场景 | 用户实时分页 | 大数据量导出 | | 最大返回 | 无限制 | 取决于设置 | 六、最佳实践 1. 组合排序字段示例: ```json "sort": [ { "create_time": "desc" }, { "score": "desc" }, { "_id": "asc" } ] ``` 2. 客户端实现逻辑: ``` 首次查询 → 保存sort值 → 下次请求携带search_after → 循环直到无结果 ``` 七、常见问题解决 1. 出现重复数据 → 检查排序字段唯一性 2. 分页中断 → 确保使用相同的排序条件 3. 性能下降 → 避免在text字段上排序 适用场景:移动端「加载更多」、日志分批处理、大数据量报表生成等需要深度分页但不需要跳页的场合。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值