李锋镝的博客

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

SpringBoot整合Elasticsearch游标查询(scroll)

2020年10月16日 496点热度 0人点赞 2条评论

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

相关文章

  • SpringBoot整合Elasticsearch详细步骤以及代码示例(附源码)
  • SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询
  • SpringBoot常用注解
  • CompletableFuture使用详解
  • SpringBoot 中内置的 49 个常用工具类
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: ElasticSearch JAVA scroll SpringBoot 搜索
最后更新:2021年5月8日

李锋镝

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

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

文章评论

  • 123456Lv 1

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

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

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

      WindowsChrome 91.0.4472.77 中国-北京市
      2021年6月30日
      回复
  • 天长地久有时尽,此恨绵绵无绝期。

    听点儿音乐吧 朋友~

    那年今日(07月07日)

    • 1983年:香港武打影星傅声去世
    • 1960年:中国大陆演员和导演英达出生
    • 1955年:中国大陆导演赵宝刚出生
    • 1930年:英国作家阿瑟·柯南·道尔去世
    • 1887年:俄国画家马克·夏加尔出生
    • 更多历史事件
    最新 热点 随机
    最新 热点 随机
    Kratos+主题新功能预览及功能演示 SpringBoot DeferredLog 完整详解 LiteLLM 本地代理搭建 Claude-HUD 使用文档 Kratos+ —— Kratos 主题二次开发记录 译文:如何将单体应用拆解为微服务
    AI时代,个人技术博客的出路在哪里?这个域名注册整整十年了,十年时间,真快啊WordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了做了一个WordPress文章热力图插件千万级大表新增字段实战指南:告别锁表与业务中断
    几款Java开发者必备常用的工具,准点下班不在话下 jmap命令(jdk1.8) 你好,2023 为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案? 提示词工程终极指南:从入门到精通的全维度实战手册 AI Agent 扩展双雄:MCP 与 Agent Skill 深度拆解——从设计哲学到实战落地
    最近评论
    李锋镝 发布于 1 天前(07月06日) 哈哈哈,你那个主题做的也很棒
    老张博客 发布于 2 天前(07月05日) 牛,这款主题几年前用过,现在被你优化的更牛X了。
    李锋镝 发布于 1 周前(06月30日) 目前是每天一换,一个星期不重样 :41:
    不凡 发布于 1 周前(06月29日) 主题配色挺好看。 :2:
    李锋镝 发布于 1 周前(06月29日) 已经更新了~
    标签聚合
    AI AI编程 数据库 MySQL SpringBoot 多线程 Redis WordPress JAVA MCP K8s ElasticSearch 架构 日常 JVM 分布式 SQL docker IDEA Spring
    友情链接
    • Blogs·CN
    • Honesty
    • Mr.Sun的博客
    • 临窗旋墨
    • 哥斯拉
    • 彬红茶日记
    • 志文工作室
    • 懋和道人
    • 拾趣博客导航
    • 搬砖日记
    • 旧时繁华
    • 林羽凡
    • 瓦匠个人小站
    • 皮皮社
    • 知向前端
    • 蜗牛工作室
    • 韩小韩博客
    • 风渡言

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    域名年龄

    Theme Kratos+ By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号