说明

es 对于 from + size 默认上限为 10000,当进行深度查询时,可以选用 scroll 方式进行查询。又称为游标查询,可以有效的进行大批量查询

使用

首次查询:
  1. curl -X POST "localhost:9200/twitter/_search?scroll=1m&pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "size": 100,
  4. "query": {
  5. "match" : {
  6. "title" : "elasticsearch"
  7. }
  8. }
  9. }
  10. '
  • size:指定每次返回的数据量,必须大于 0,该字段作用于单个分片,所以每个批次返回的最大文档数量为 size * number_of_primary_shards(新版本每次正确返回相应的数量)
  • scroll=1m:保持游标查询窗口一分钟(它的值不需要长到能够处理完所有的数据,只要足够处理前一批结果就行了。每个 scroll 请求都会设置一个新的过期时间)
    注:新版本中的 scroll_id 每次返回均一致

scroll 查询:

首次查询会返回 _scroll_id 字段,将该字段值传入 scroll API 来获取下一批数据。

  1. curl -X POST "localhost:9200/_search/scroll?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "scroll" : "1m",
  4. "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
  5. }
  6. '

排序方式

在不需要关系排序的情况下,可以使用 _doc 进行排序,es 在 5.x 的版本之后对该情况进行了优化,如:

  1. curl -XGET 'localhost:9200/_search?scroll=1m&pretty' -H 'Content-Type: application/json' -d'
  2. {
  3. "size": 100,
  4. "query": {
  5. "match" : {
  6. "title" : "elasticsearch"
  7. }
  8. },
  9. "sort": [
  10. "_doc"
  11. ]
  12. }
  13. '

注: 高版本中 search_type=scan 等操作已废弃

原理

服务器保持查询上下文一直存在来达到该目的。通常,为了优化索引,后台合并进程会把较小的段合并在一起创建出新的更大的段,此时会删除较小的段。这个过程在 scrolling 期间会继续进行,但是一个打开状态的索引上下文可以防止旧段在仍需要使用时被删除。这就解释了 Elasticsearch 为什么能够不考虑对文档的后续修改,而返回初始搜索请求的结果。

TIP:使旧段保持活动状态意味着需要更多的文件句柄。请确保你已将节点配置为拥有足够的可用的文件句柄。

参考

  1. elastic.co/guide/en/elasticsearch/reference/6.3/search-request-scroll.html
  2. https://www.elastic.co/guide/cn/elasticsearch/guide/current/scroll.html
  3. https://www.cnblogs.com/wangzhuxing/p/9569727.html
  4. https://www.jianshu.com/p/91d03b16af77
  5. https://www.jianshu.com/p/bdf98307d984
  6. http://arganzheng.life/deep-pagination-in-elasticsearch.html