SpringBoot整合Elasticsearch游标查询的示例代码(scroll)

 更新时间:2020年10月16日 16:48:28   作者:李锋镝的园子  
这篇文章主要介绍了SpringBoot整合Elasticsearch游标查询(scroll),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

游标查询(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<Map> commonStartScroll(Map<String, String> params, String indexName, String type, String defaultSort,
                 Map<Key, FieldDefinition> keyMappings,
                 Map<String, Map<Key, FieldDefinition>> 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<Map> 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<Map> scroll(Map<String, String> 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<String, String> 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/archives/article/2119

到此这篇关于SpringBoot整合Elasticsearch游标查询(scroll)的文章就介绍到这了,更多相关SpringBoot整合Elasticsearch内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot实现自定义事件的方法详解

    SpringBoot实现自定义事件的方法详解

    这篇文章将用实例来和大家介绍一下如何在SpringBoot中自定义事件来使用观察者模式。文中的示例代码讲解详细,对我们学习SpringBoot有一定的帮助,需要的可以参考一下
    2022-06-06
  • java实现飞机大战案例详解

    java实现飞机大战案例详解

    这篇文章主要为大家详细介绍了java实现飞机大战案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • Java的Shiro框架认证流程详解

    Java的Shiro框架认证流程详解

    这篇文章主要介绍了Java的Shiro框架认证流程详解,Shiro 是一个功能强大和易于使用的安全框架,为开发人员提供一个直观而全面的解决方案的认证,授权,加密,会话管理四大功能,需要的朋友可以参考下
    2024-01-01
  • springboot+websocket实现并发抢红包功能

    springboot+websocket实现并发抢红包功能

    本文主要介绍了springboot+websocket实现并发抢红包功能,主要包含了4种步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • ExecutorService Callable Future多线程返回结果原理解析

    ExecutorService Callable Future多线程返回结果原理解析

    这篇文章主要为大家介绍了ExecutorService Callable Future多线程返回结果,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 基于Java实现的Base64加密、解密原理代码

    基于Java实现的Base64加密、解密原理代码

    这篇文章主要介绍了基于Java实现的Base64加密、解密原理代码,需要的朋友可以参考下
    2014-07-07
  • Jmeter配置代理实现录制过程图解

    Jmeter配置代理实现录制过程图解

    这篇文章主要介绍了Jmeter配置代理实现录制过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Java中Base64和File之间互转代码示例

    Java中Base64和File之间互转代码示例

    这篇文章主要给大家介绍了关于Java中Base64和File之间互转的相关资料,Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法,需要的朋友可以参考下
    2023-08-08
  • springcloud 整合 openfeign的方法

    springcloud 整合 openfeign的方法

    openFeign 是springcloud对Feign进行了增强,使得Feign支持了springmvc的注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便,这篇文章主要介绍了springcloud 整合 openfeign,需要的朋友可以参考下
    2022-09-09
  • Spring AOP实现用户登录统一验证功能

    Spring AOP实现用户登录统一验证功能

    这篇文章主要为大家详细介绍了Spring AOP如何实现用户登录统一验证功能,文中的示例代码讲解详细,对我们学习具有一定的借鉴价值,需要的可以参考一下
    2023-01-01

最新评论