关于java:Elasticsearch-实现分页的-3-种方式还有谁不会

2次阅读

共计 2383 个字符,预计需要花费 6 分钟才能阅读完成。

一、from + size 浅分页

“ 浅 ” 分页能够了解为简略意义上的分页。

它的原理很简略,就是查问前 20 条数据,而后截断前 10 条,只返回 10-20 的数据。这样其实白白浪费了前 10 条的查问。

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {"age": 28}
        }
      ]
    }
  },
  "size": 10,
  "from": 20,
  "sort": [
    {
      "timestamp": {"order": "desc"},
      "_id": {"order": "desc"}
    }
  ]
}

其中,from 定义了指标数据的偏移值,size 定义以后返回的数目。默认 from 为 0,size 为 10,即所有的查问默认仅仅返回前 10 条数据。

在这里有必要理解一下 from/size 的原理:

因为 es 是基于分片的,假如有 5 个分片,from=100,size=10。则会依据排序规定从 5 个分片中各取回 100 条数据数据,而后汇总成 500 条数据后抉择最初面的 10 条数据。

做过测试,越往后的分页,执行的效率越低。总体上会随着 from 的减少,耗费工夫也会减少。而且数据量越大,就越显著!

二、scroll 深分页

from+size 查问在 10000-50000 条数据(1000 到 5000 页)以内的时候还是能够的,然而如果数据过多的话,就会呈现深分页问题。

为了解决下面的问题,elasticsearch 提出了一个 scroll 滚动的形式。

scroll 相似于 sql 中的 cursor,应用 scroll,每次只能获取一页的内容,而后会返回一个 scroll_id。依据返回的这个scroll_id 能够一直地获取下一页的内容,所以 scroll 并不适用于有跳页的情景。

GET test_dev/_search?scroll=5m
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {"age": 28}
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "sort": [
    {
      "timestamp": {"order": "desc"},
      "_id": {"order": "desc"}
    }
  ]
}
  • scroll=5m示意设置 scroll_id 保留 5 分钟可用。
  • 应用 scroll 必须要将 from 设置为 0。
  • size 决定前面每次调用 _search 搜寻返回的数量

而后咱们能够通过数据返回的 _scroll_id 读取下一页内容,每次申请将会读取下 10 条数据,直到数据读取结束或者 scroll_id 保留工夫截止:

GET _search/scroll
{
  "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",
  "scroll": "5m"
}

留神:申请的接口不再应用索引名了,而是 _search/scroll,其中 GET 和 POST 办法都能够应用。

scroll 删除

依据官网文档的说法,scroll 的搜寻上下文会在 scroll 的保留工夫截止后主动革除,然而咱们晓得 scroll 是十分耗费资源的,所以一个倡议就是当不须要了 scroll 数据的时候,尽可能快的把 scroll_id 显式删除掉。

革除指定的scroll_id

DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....

革除所有的 scroll:

DELETE _search/scroll/_all

三、search_after 深分页

scroll 的形式,官网的倡议不用于实时的申请(个别用于数据导出),因为每一个 scroll_id 不仅会占用大量的资源,而且会生成历史快照,对于数据的变更不会反映到快照上。

search_after 分页的形式是依据上一页的最初一条数据来确定下一页的地位,同时在分页申请的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。然而须要留神,因为每一页的数据依赖于上一页最初一条数据,所以无奈跳页申请。

为了找到每一页最初一条数据,每个文档必须有一个全局惟一值,官网举荐应用 _uid 作为全局惟一值,其实应用业务层的 id 也能够。

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {"age": 28}
        }
      ]
    }
  },
  "size": 20,
  "from": 0,
  "sort": [
    {
      "timestamp": {"order": "desc"},
      "_id": {"order": "desc"}
    }
  ]
}
  • 应用 search_after 必须要设置from=0
  • 这里我应用 timestamp 和 _id 作为惟一值排序。
  • 咱们在返回的最初一条数据里拿到 sort 属性的值传入到search_after

应用 sort 返回的值搜寻下一页:

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {"age": 28}
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "search_after": [
    1541495312521,
    "d0xH6GYBBtbwbQSP0j1A"
  ],
  "sort": [
    {
      "timestamp": {"order": "desc"},
      "_id": {"order": "desc"}
    }
  ]
}

你都学会了吗?

版权申明:本文为 CSDN 博主「zhexiao27」的原创文章,遵循 CC 4.0 BY-SA 版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/andybeg…

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿(2022 最新版)

2. 劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0