李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 每日心情
  • Now
  • 系列文章
  • 论坛
  • 左邻右舍
    • 左邻右舍
    • 博友圈
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于我
    • 网站地图
    • 网站统计
    • 另一个网站
    • 我的导航站
    • 赞助
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. 原创
  3. 正文

SpringBoot整合Elasticsearch游标查询(scroll)

2020年10月16日 约 1,072 字4 分钟 84 0 2
本文最后更新于 2021年5月8日,距今已 1940 天,其中的信息可能已经发生变化,请注意甄别。

游标查询(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

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

谢谢~~

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/article/2119

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: ElasticSearch JAVA scroll SpringBoot 搜索
最后更新:2021年5月8日
相关文章
  • SpringBoot使用RestTemplate进行接口调用2021年1月19日
  • Java中的字符和字符串2022年7月18日
  • JMX监控权限认证配置2021年8月6日
  • 如何查看JVM参数2020年8月3日
  • 分布式锁-Java常用技术方案2019年11月11日

李锋镝

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

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

文章评论

  • blank
    123456Lv 1

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

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

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

      WindowsChrome 91.0.4472.77 中国-北京
      2021年6月30日
      00 回复
  • 行是知之始,知是行之成。

    听点儿音乐吧 朋友~
    文章目录
    最新 热点 随机
    最新 热点 随机
    快速习得技能的十个方法(关键20小时,快速学会任何技能) 记录一下PHP升级8.5遇到的坑 本来想把主题上传到WordPress官方主题商店的,结果懵逼了…… 英伟达 H100 是啥,到底好在哪? Kafka Log Compaction(日志压缩)详解 WordPress缓存插件WP Fastest Cache、WP Rocket 、FlyingPress对比
    给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能Kratos+ v1.1.16版本更新说明AI时代,个人技术博客的出路在哪里?增加了两套复古皮肤-牛皮纸、千禧网页写了一个订阅每日新闻的WP插件WordPress缓存插件WP Fastest Cache、WP Rocket 、FlyingPress对比
    n8n深度解析:可视化编排与灵活拓展的双引擎驱动 Eclipse快捷键 redis异常记录 透过现象看本质:Java类动态加载和热替换 MySQL中的这个池子,强的一批! 从零开始入门 K8s | Kubernetes 网络概念及策略控制
    最近评论
    blank
    李锋镝 发布于 8 小时前(08月30日) 一切都要从升级数据库开始说起~折腾上瘾了
    blank
    Hary 发布于 8 小时前(08月30日) 用8.0感觉都很新了,没必要随时更新最新的吧,不过或者就是折腾,遇见问题解决问题
    blank
    李锋镝 发布于 1 天前(08月29日) 很中肯的建议了~
    blank
    不凡 发布于 2 天前(08月29日) 当前运行环境无任何问题,能不升级就不要升级,我的网站除了主题,好久没升级了。
    blank
    李锋镝 发布于 2 天前(08月28日) 那你很幸运了~
    标签聚合
    Claude IDEA MySQL ElasticSearch 日常 Spring 多线程 SQL 数据库 WordPress Redis MQ JAVA 分布式 架构 JVM AI编程 K8s SpringBoot AI
    友情链接
    • 知向前端
    • sssr7844的博客
    • 哥斯拉
    • 九仞之行
    • 懋和道人
    • 老张博客
    • Mr.Sun的博客
    • 彬红茶日记
    • 搬砖日记
    • 韩情脉脉
    • 林羽凡
    • Serendipity
    • 蜗牛工作室
    • 瓦匠个人小站
    • 皮皮社
    • 若梦博客
    • 志文工作室
    • 临窗旋墨
    • Honesty
    • 韩小韩博客

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    正在博友圈履约中

    域名年龄

    Theme Kratos-plus By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号