golang ES From size 分页查询 和 Scroll 分页查询 demo

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: golang ES From size 分页查询 和 Scroll 分页查询 demo

From Size 方式分页查询 demo

func TestESQueryDemo(client *elastic.Client) {
        // ES SDK 教程:https://www.yisu.com/zixun/694102.html
  query := elastic.NewBoolQuery().
                Must(elastic.NewMatchQuery("lastname", "smith")).
    Filter(elastic.NewTermQuery("age", "20")).
    Filter(elastic.NewRangeQuery("modify_time").Format("yyyy-MM-dd").Gte("2021-07-22").Lt("2021-07-23"))
  ctx := context.Background()
  index := "info"
  result, err := client.Search(index).Query(query).Size(20).From(0).Do(ctx)
  if err != nil {
        logs.Error("err=%v", err)
  }
  for page, hit := range result.Hits.Hits {
    //var t Employee
    //err := json.Unmarshal(*hit.Source, &t) //另一种取出的方法
    //if err != nil {
    //  fmt.Println("failed")
    //}
    //fmt.Printf("employee name %s:%s\n", t.FirstName, t.LastName)
    logs.Info("page=%v, hit=%v", page, hit)
  }
  logs.Info("result=%v, err=%v", *result.Hits, err)
}

其他 api 使用参考:go语言操作es的方法

Scroll 分页查询 demo

Form Size 方式最多查一万条记录(是总共 1w,不是单次 1w,就算每次只查 1 条,查 10000 次之后也会报错),即 from + size <= 10000,当索引第 10001 条数据时,会报错,比如当我设置 from=10000,size=1,查询时提示 Type: illegal_argument_exception, Reason: Result window is too large, from + size must be less than or equal to: [10000] but was [10001]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.

当所请求的数据总量大于1w时,可用scroll来代替from+size。

scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询。游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引视图一样。

func TestESQueryDemo(client *elastic.Client) {
   defer logs.Flush()
   query := elastic.NewBoolQuery().
        Must(elastic.NewMatchQuery("lastname", "smith")).
        Filter(elastic.NewTermQuery("age", "20")).
        Filter(elastic.NewRangeQuery("modify_time").Format("yyyy-MM-dd").Gte("2021-07-22").Lt("2021-07-23"))
   ctx := context.Background()
   index := "info"
   result, err := client.Scroll(index).
      Query(query).
      Scroll("8s"). // 这个时间只需要能查到第一次时间片就够了,不是查询所有文档的时间
      Size(200).
      Do(ctx)
   scrollID := result.ScrollId
   logs.Info("total = %d, result=%v, err=%v", result.TotalHits(), *result.Hits, err)
   for {
      result, err = client.Scroll("2s").ScrollId(scrollID).Do(ctx) // 每次查询都会使用这个时间续期
      logs.Info("total = %d, result=%v, err=%v", result.TotalHits(), *result.Hits, err)
      if len(result.Hits.Hits) <= 0 {
         break
      }
      logs.Info("scrollID = %v", result.ScrollId)
      time.Sleep(1 * time.Second)
   }
   // 清除游标
   _, err = client.ClearScroll().ScrollId(result.ScrollId).Do(ctx)
}

关于 Scroll 查询返回 返回 EOF 错误

使用 Scroll 来分页查询,如果首次查询时发现无有效记录,即首次查询结果为空时,那么会返回 EOF 错误,而不是空的结果列表。此时,需要我们做一个判断,究竟是 EOF 错误则认为是返回结果为空,否则认为是发生了错误

if err == io.EOF {
  fmt.Println("the error equal io.EOF")
}
if err.Error() == "EOF" {
  fmt.Println("the error.Error() equal io.EOF")
}
fmt.Println(err) // 查询错误,而非数据为空

关于 Scroll 时间参数的说明

启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间。

游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。

这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。

设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。

参考:es scroll 时间_游标查询 Scroll | Elasticsearch: 权威指南 | ElasticElasticsearch的滚动查询---Scroll,解决ES每次最多查一万笔数据的问题

两种分页查询方式的对比

ES对于from+size的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替from+size。

ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。 Query阶段比较轻量级,通过查询倒排索引,获取满足查询结果的文档ID列表。 而Fetch阶段比较重,需要将每个shard的结果取回,在协调结点进行全局排序。 通过From+size这种方式分批获取数据的时候,随着from加大,需要全局排序并丢弃的结果数量随之上升,性能越来越差。

而Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也就是doc id列表保留在一个上下文里, 之后每次分批取回的时候,只需根据设置的size,在每个shard内部按照一定顺序(默认doc_id续), 取回这个size数量的文档即可。

由此也可以看出scroll不适合支持那种实时的和用户交互的前端分页工作,其主要用途用于从ES集群分批拉取大量结果集的情况,一般都是offline的应用场景。 比如需要将非常大的结果集拉取出来,存放到其他系统处理,或者需要做大索引的reindex等等。 不要把 scroll 用于实时请求,它主要用于大数据量的场景。例如:将一个索引的内容索引到另一个不同配置的新索引中。

参考:es scroll 时间_ElasticSearch教程之---Scroll查询mongo 返回EOF错误

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
人工智能 Go
Golang 搭建 WebSocket 应用(二) - 基本群聊 demo
Golang 搭建 WebSocket 应用(二) - 基本群聊 demo
29 1
|
JSON Linux Go
Golang之我想写个"web框架"-7: 完成一个“留言小demo”
Golang之我想写个"web框架"-7: 完成一个“留言小demo”
156 0
Golang:go-querystring将struct编码为URL查询参数的库
Golang:go-querystring将struct编码为URL查询参数的库
233 0
golang 协程并发代码 demo
golang 协程并发代码 demo
|
Java Linux Go
知识分享之Golang——Bleve中查询时指定具体字段Field和权重
知识分享之Golang篇是我在日常使用Golang时学习到的各种各样的知识的记录,将其整理出来以文章的形式分享给大家,来进行共同学习。欢迎大家进行持续关注。 知识分享系列目前包含Java、Golang、Linux、Docker等等。
129 0
知识分享之Golang——Bleve中查询时指定具体字段Field和权重
|
Go 前端开发
golang(3):beego CRUD demo (1)
本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/46699343 转载请一定注明出处! 1,beego 自带crud生成工具 工具执行非常简单: bee generate scaffold post -fields="title:string,body:text" 设置模块post,里面的file
1552 0
|
1月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
53 4
Golang语言之管道channel快速入门篇
|
1月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
46 4
Golang语言文件操作快速入门篇
|
1月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
53 3
Golang语言之gRPC程序设计示例