李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 系列
  • AI工具集
  • 论坛
  • 友圈
    • 友链
    • 朋友圈
    • 游客中心
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于本站
    • Now
    • 每日心情
    • 网站地图
    • 网站统计
    • 赞助
  • 星球穿梭
  • 🚇开往
静亦定 动亦定
惟坚韧者始能遂其志
  1. 首页
  2. 原创
  3. 正文

SpringBoot整合Elasticsearch游标查询(scroll)

2020年10月16日 243 0 2
本文最后更新于 2021年5月8日,距今已 1993 天,其中的信息可能已经发生变化,请注意甄别。

游标查询(scroll)简介

scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。

游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引 视图 一样。

启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间。 游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。

GET /old_index/_search?scroll=1m 
{
    "query": { "match_all": {}},
    "sort" : ["_doc"], 
    "size":  1000
}

scroll=1m:保持游标查询窗口一分钟。

返回结果示例:

{
    "_scroll_id": "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs=",
    "took": 10,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 2633253,
        "max_score": 1.0,
        "hits": [
            {
                "_index": "old_index",
                "_type": "old_index_type",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    ...
                }
            }
        ]
    }
}

这个查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串 。 现在我们能传递字段 _scroll_id 到 _search/scroll 查询接口获取下一批结果:

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs="
}

注意:需要再次设置游标查询过期时间为一分钟。

这个游标查询返回下一批结果。

另外尽管我们指定字段 size 的值为1000,但是我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards。

注意:游标查询每次返回一个新字段 _scroll_id。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段_scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。

整合

新增以下三个方法:

/**
 * 游标查询
 * @param params 查询入参
 * @param indexName 索引名称
 * @param type 索引类型
 * @param defaultSort 默认排序
 * @param keyMappings 字段映射
 * @param keyMappingsMap 索引对应字段映射
 * @param scrollTimeInMillis 游标开启的时间
 * @return Page
 */
protected Page commonStartScroll(Map params, String indexName, String type, String defaultSort,
                                 Map keyMappings,
                                 Map> keyMappingsMap, long scrollTimeInMillis) {
    SearchQuery searchQuery = buildSearchQuery(params, indexName, type, defaultSort, keyMappings, keyMappingsMap);
    return elasticsearchTemplate.startScroll(scrollTimeInMillis, searchQuery, Map.class);
}

/**
 * 游标查询
 * @param scrollId 游标ID
 * @param scrollTimeInMillis 游标开启的时间
 * @return Page
 */
protected Page commonContinueScroll(String scrollId, long scrollTimeInMillis) {
    return elasticsearchTemplate.continueScroll(scrollId, scrollTimeInMillis, Map.class);
}

/**
 * 根据游标ID清除游标(提早释放资源,降低ES的负担)
 * @param scrollId 游标ID
 */
protected void clearScroll(String scrollId) {
    elasticsearchTemplate.clearScroll(scrollId);
}

StoreSearchService中增加游标查询方法以及清除游标方法:

/**
 * 游标查询
 * @param params 查询条件
 * @return page
 */
public Page scroll(Map params) {
    IndexConfig config = indexEntity.getConfigByDocCode(DOC_CODE);

    // 如果请求参数包含游标ID,则说明执行翻页操作,否则认为开启新的游标查询
    String scrollId = params.getOrDefault(SCROLL_ID, null);
    if (StringUtils.isNotBlank(scrollId)) {
        return commonContinueScroll(params.get(scrollId), config.getScrollTimeInMillis());
    }
    return commonStartScroll(params, config.getIndexName(), config.getType(), DEFAULT_SORT,
            keyMappings, keyMappingsMap, config.getScrollTimeInMillis());
}
public void clearScroll(String scrollId) {
    super.clearScroll(scrollId);
}

对外暴露接口:

@PostMapping("/scroll")
public ResponseResult scroll(@RequestBody Map params) {

    return ResponseResult.success(storeSearchService.scroll(params));
}

@GetMapping("/scroll/clear/{scrollId}")
public ResponseResult clearScroll(@PathVariable String scrollId) {
    storeSearchService.clearScroll(scrollId);
    return ResponseResult.success(null);
}

游标查询分为开启和继续两个步骤,接口/scroll中根据_scrollId判断为开启游标查询还是继续游标查询。

若条件允许的话,尽量将游标查询及时关闭,以释放ES集群的资源,降低负担。

源码

Git项目地址:https://github.com/lifengdi/search

如果觉得有帮助的话,请帮忙点赞、点星小小的支持一下~

谢谢~~

参考链接

1
  1. 1https://github.com/lifengdi/searchgithub.com
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
分享到

SpringBoot整合Elasticsearch游标查询(scroll)

也可使用浏览器菜单中的「分享」功能

微信扫一扫分享

标签: ElasticSearch JAVA scroll SpringBoot 搜索
最后更新:2021年5月8日

岁月同一天 10 月 23 日

回望过去的今天,你在写什么

  • 后端
    1 年前 2025年10月23日
    深入解析 localhost 与 127.0.0.1:不止于“本地访问”的技术细节

    在日常开发中,我们总会在浏览器地址栏、配置文件或代码里看到 localhost 和 127.0.0.1 的身影。多数时候…

  • AI
    1 年前 2025年10月23日
    Claude Code提示词优化指南:从"瞎写"到"高效生成",开发效率提升10倍的实战秘籍

    用Claude Code时,你是否常遇到这些问题:生成的代码过时(如用Vue 2写登录组件)、对话久了AI忘记技术栈、复…

  • 技术
    7 年前 2019年10月23日
    Kubernetes(K8s)的Service运行原理

    一、为什么Servcie能定位到Pod 因为Pod的IP是不固定的,所以Kubernetes需要Service,除此之外…

相关文章
  • 使用springboot结合AI生成视频2025年3月9日
  • mybatis-plus-join-boot-starter介绍及用法2025年4月24日
  • SpringBoot DeferredLog 完整详解2026年6月18日
  • 关于Elasticsearch文档的描述以及如何操作文档的详细总结2019年9月18日
  • 全网最全Shiro认证与授权原理分析2021年2月16日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

  • 123456Lv 1

    作为一个初学者没太搞懂,配置文件里面需要修改的参数没有说明,给出的调用接口没有给具体参数和说明看的很糊涂。

    WindowsWindowsChrome 91.0.4472.106Chrome 91.0.4472.106中国中国-河南-郑州
    2021年6月22日
    00 回复
    • 李锋镝Lv 5

      @123456 抱歉哈,以后有时间了会给这块补上的。

      WindowsWindowsChrome 91.0.4472.77Chrome 91.0.4472.77中国中国-北京
      2021年6月30日
      00 回复
  • 我是人间惆怅客,知君何事泪纵横,断肠声里忆平生。

    听点儿音乐吧 朋友~
    文章目录
    最新 热点 随机
    最新 热点 随机
    php2shell远程执行漏洞修复(CVE-2026-109618 和 CVE-2026-109619) 聊一聊DeepSeek开放自研搜索API这事 Let's Encrypt宣布证书缩短至64天,手动时代彻底终结! Markdown 的前世今生 讨论下XXL-JOB GLUE模式的安全问题 心气没了,干什么都不得劲
    给主题增加了游客中心功能心气没了,干什么都不得劲我觉得是时候公布我的导航网站了游本昌去世关于主题加载速度优化的一点儿小演进给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能
    Kafka常见面试题(一) 提示词工程终极指南:从入门到精通的全维度实战手册 Eclipse反编译插件Jad安装 JVM参数中的-D是什么意思 JVM详细参数说明 Spring Boot 指定外部配置文件的方式
    最近评论
    fairy 发布于 2 小时前(10月23日) 我挺支持这个的,自己的站,还是要看看的。证书过期都不知道,还不如关站算了。
    fairy 发布于 2 小时前(10月23日) 我小站,直接apt update && apt upgrade 就解决了,现在是8....
    李锋镝 发布于 16 小时前(10月22日) 赞!置顶了,让更多人看到~
    秋风于渭水 发布于 16 小时前(10月22日) 会把Docker里的遗漏的,`ps aux | grep php-fpm`直接看有多少对外的 PHP...
    李锋镝 发布于 16 小时前(10月22日) 独立博客还真说不好是不是好事……
    标签聚合
    SpringBoot 日常 分布式 JVM Claude K8s AI Spring ElasticSearch 多线程 JAVA AI编程 Redis MySQL WordPress IDEA Theme 数据库 SQL 架构
    友情链接
    • 九仞之行
    • 懋和道人
    • 韩小韩博客
    • lijie blog
    • 韩情脉脉
    • 搬砖日记
    • 彬红茶日记
    • 知向前端
    • 老张博客
    • 刘永博客
    • 志文工作室
    • Honesty
    • Serendipity
    • Mr.Sun的博客
    • 瓦匠个人小站
    • sssr7844的博客
    • 哥斯拉
    • 皮皮社
    • 林羽凡

    COPYRIGHT © 2016-2026 lifengdi.com. ALL RIGHTS RESERVED.

    lifengdi.com 十年之约虫洞

    Domain age badge for lifengdi.com

    Theme Kratos-plus By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号