【问题标题】:Elasticsearch Scroll弹性搜索滚动
【发布时间】:2018-03-18 04:04:24
【问题描述】:

我对 Elasticsearch 的滚动功能有点困惑。 在弹性搜索中,每当用户在结果集上滚动时,是否可以调用搜索 API? 来自文档

"search_type" => "scan",    // use search_type=scan
"scroll" => "30s",          // how long between scroll requests. should be small!
"size" => 50,               // how many results *per shard* you want back

这是否意味着它将每 30 秒执行一次搜索并返回所有结果集,直到没有记录?

例如,我的 ES 返回总共 500 条记录。我从 ES 获取数据作为两组记录,每组记录有 250 条记录。有什么办法可以先显示第一组 250 条记录,当用户滚动时,再显示第二组 250 条记录。请建议

【问题讨论】:

    标签: elasticsearch scroll pagination


    【解决方案1】:

    你要找的是分页。

    您可以通过查询固定大小并设置from 参数来实现您的目标。由于要设置分批显示 250 个结果,因此可以设置 size = 250 并随着每个连续查询,将 from 的值增加 250

    GET /_search?size=250                     ---- return first 250 results
    GET /_search?size=250&from=250            ---- next 250 results 
    GET /_search?size=250&from=500            ---- next 250 results
    

    相反,Scan & scroll 可让您通过一次搜索检索大量结果,非常适合将数据重新索引到新索引等操作。不建议使用它来实时显示搜索结果。

    简单解释一下Scan & scroll,它本质上是扫描索引以查找随扫描请求提供的查询并返回scroll_id。这个scroll_id可以传递给下一个滚动请求返回下一批结果。

    考虑以下示例-

        # Initialize the scroll
        page = es.search(
          index = 'yourIndex',
          doc_type = 'yourType',
          scroll = '2m',
          search_type = 'scan',
          size = 1000,
          body = {
            # Your query's body
            }
        )
        sid = page['_scroll_id']
        scroll_size = page['hits']['total']
          
        # Start scrolling
        while (scroll_size > 0):
          print "Scrolling..."
          page = es.scroll(scroll_id = sid, scroll = '2m')
          # Update the scroll ID
          sid = page['_scroll_id']
          # Get the number of results that we returned in the last scroll
          scroll_size = len(page['hits']['hits'])
          print "scroll size: " + str(scroll_size)
          # Do something with the obtained page
    

    在上面的例子中,发生了以下事件-

    • 滚动条已初始化。这将返回第一批结果以及 scroll_id
    • 对于每个后续滚动请求,都会发送更新后的scroll_id(在上一个滚动请求中收到)并返回下一批结果。
    • 滚动时间基本上是搜索上下文保持活动的时间。如果在设置的时间范围内没有发送下一个滚动请求,则搜索上下文丢失并且不会返回结果。这就是为什么它不应该用于具有大量文档的索引的实时结果显示。

    【讨论】:

    • scroll = '2m' 是什么意思?是2分钟的意思吗?它有什么用?
    • @AmoghMishra 是的,这意味着 2 分钟
    • @AmoghMishra 滚动获取查询的快照,这就是它在内存中存储的时间。这意味着如果您添加/更新记录,后续滚动将不会看到它们。
    • "search_type=scan" 已被弃用,并在 v5.0 中被删除。你不需要它
    • 您希望 sid 每次都不同吗?我每次都得到相同的 sid。会有什么问题?
    【解决方案2】:

    在最新版本的 Elasticsearch 中,您将使用 search_after。您在此处设置的keep_alive,就像滚动中的timeout,只是您处理一页所需的时间。

    那是因为 Elasticsearch 会让您的“搜索上下文”在这段时间内保持活跃,然后将其删除。此外,Elasticsearch 不会自动为您获取下一页,您必须通过发送带有上一个请求的 ID 的请求来做到这一点。

    【讨论】:

      【解决方案3】:

      使用滚动 api 是明智的,因为在 elasticsearch 中一次无法获取超过 10K 的数据。

      【讨论】:

        【解决方案4】:

        Scroll API at elastic 的文档也解释了这种行为。

        10k 的结果大小是默认值,如果需要,可以在运行时覆盖:

        PUT { "index" : { "max_result_window" : 500000} }
        

        滚动 id 的生命周期在每个滚动请求中使用参数“scroll”定义,例如

        ..
          "scroll" : "5m"
          ..
        

        【讨论】:

          【解决方案5】:

          您作为示例用例描述的实际上是search results pagination,它可用于任何搜索查询,并且受限于 10k 个结果。当您需要超过 10k 限制时,需要 scroll 请求,使用 scroll 查询,您甚至可以获取整个文档集合。

          这里可能造成混淆的原因是scroll 术语不明确:它表示查询的类型,也是该查询的参数名称(正如other comments 中提到的,是时候了ES 会一直等待你获取下一个滚动块)。

          scroll 查询很繁重,除非绝对必要,否则应避免使用。其实在docs 它说:

          滚动不是为了实时用户请求,而是为了处理大量数据,...

          现在关于您的另一个问题:

          在elasticsearch中是否可以在每次用户滚动结果集时调用搜索API?

          是的,甚至几个parallel scroll requests 是可能的:

          每个滚动都是独立的,可以像任何滚动请求一样并行处理。

          【讨论】:

            【解决方案6】:

            您理解错误scroll 属性的用途。这并不意味着 elasticsearch 会在 30 秒后获取下一页数据。当您进行第一次滚动请求时,您需要指定何时应关闭滚动上下文。 scroll 参数告诉在 30 秒后关闭滚动上下文。

            在执行第一次滚动请求后,您将返回 scroll_idparameter 作为响应。对于下一页,您需要传递该值以获取滚动响应的下一页。如果您未在 30 秒内执行下一个滚动请求,则滚动请求将被关闭,您将无法获取该滚动请求的下一页。

            【讨论】:

            • 当新的scroll_id和context生成或者所有scroll_ids和它们的context保持激活直到指定的时间到期或者所有的数据已经滚动通过时,之前的scroll_id和它的context是否会自动清除?
            • id 将保持活动状态直到指定时间结束,您可以有多个滚动上下文,每个都有其生命
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-15
            • 1970-01-01
            • 2021-11-23
            • 1970-01-01
            • 2018-10-26
            相关资源
            最近更新 更多