迁移至Spring Data Elasticsearch 3.x后,Scan & Scroll的替代方案咨询
Spring Data Elasticsearch 3.x中Scan & Scroll的替代方案
没错,Spring Data Elasticsearch 3.x确实移除了ElasticsearchTemplate里的scan()方法——这是因为ES 5.x+官方已经不再推荐使用Scan API,转而统一用Scroll API实现大数据集的批量查询。不过不用担心,Spring Data Elasticsearch 3.x提供了一组贴合ES原生滚动逻辑的方法来替代,就是searchScrollStart()、searchScrollContinue()和searchScrollClear()。
下面给你一个完整的代码示例,对应你的需求场景:
步骤1:初始化滚动查询,获取第一批结果与scrollId
// 构建你的查询条件,这里用matchAllQuery做示例,可替换为你的业务查询 SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withPageable(PageRequest.of(0, 1000)) // 每次滚动获取的条数,根据内存情况调整(建议1000-5000) .build(); // 初始化滚动,设置scroll过期时间(单位毫秒,这里设为1分钟) ScrollHits<SampleEntity> scrollHits = elasticsearchOperations.searchScrollStart(60000, searchQuery, SampleEntity.class); String scrollId = scrollHits.getScrollId(); List<SampleEntity> allResults = new ArrayList<>(); // 先存入第一批查询结果 allResults.addAll(scrollHits.getSearchHits());
步骤2:循环滚动获取剩余数据
// 只要还有未获取的结果,就继续滚动查询 while (scrollHits.hasSearchHits()) { // 继续获取下一批数据 scrollHits = elasticsearchOperations.searchScrollContinue(scrollId, 60000, SampleEntity.class); allResults.addAll(scrollHits.getSearchHits()); // 更新scrollId用于下一次滚动 scrollId = scrollHits.getScrollId(); }
步骤3:清理Scroll上下文,释放ES资源
// 务必清理scrollId,避免占用ES的服务器资源 elasticsearchOperations.searchScrollClear(Collections.singletonList(scrollId));
额外注意事项
- 每次滚动的page size不要过大,否则容易引发内存溢出,根据你的应用内存情况调整即可
- Scroll过期时间要设置合理:既要保证能处理完当前批次的数据,又不要过长(比如处理一批数据需要30秒,设1分钟就足够)
- 如果处理超大规模数据集,建议在循环中做分批处理(比如每积累10万条就处理一次,然后清空临时集合),避免内存占用过高
内容的提问来源于stack exchange,提问作者priyanshu goyal
相关产品推荐
相关产品推荐

