• 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错误

  • 相关阅读:
    HTML5 拖放(Drag 和 Drop)详解与实例
    JS中的六大数据类型
    关于创建本地docker仓库
    关于使用国内dock仓库,网易、DaoCloud
    关于Docker开通远程访问端口2375
    多个消费者监听同一个队列
    SQLite -附加数据库
    解密JDK8 枚举
    LoraLU
    深入理解display属性
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/16611411.html
Copyright © 2020-2023  润新知