深度剖析ElasticSearch分页原理与深分页问题|ES深分页问题|ES分页原理剖析

文章目录

  • ES分页|Paginate search results
    • ES深分页的问题
      • 一页获取数据量太大,报错
      • 分页深度太大,报错
      • 官方解释
    • 其他解决方案
    • Search after
      • 解决两个问题
    • 有没有深分页查询的必要性?
    • search after & PIT的使用方式
      • 1.创建pit
      • 2.首次查询
      • 3.之后的查询
        • 延伸
      • 4.清除pit
    • 滚动搜索|Scroll search results

ES分页|Paginate search results

Paginate search results

By default, searches return the top 10 matching hits.

To page through a larger set of results, you can use the search API’s from and size parameters.

The from parameter defines the number of hits to skip, defaulting to 0.

The size parameter is the maximum number of hits to return.

Together, these two parameters define a page of results.

ESfromsize两个参数定义了一页数据的结果:

from——

跳过多少个doc,

默认地"from":0, 则跳过0个文档,即从第一个doc开始取,即角标第0条数据开始,取size个doc;

“from”:10, 即跳过10个doc,从角标第0个doc开始到角标第9个doc为止,是10个doc,跳过这10个doc,即从第11个doc开始取,即角标为10的doc开始取,取size个doc。

则,可以得知,“from”: m, 就是代表着从角标为m的doc开始取(角标为m的doc包含在内),取size个doc,构成一页(page)数据。

对比关系型数据库,如MySQL的语法是

[LIMIT {[offset,] row_count | row_count OFFSET offset}]`


With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

这个示例使用的limit offset, row_count,表示跳过offset条数据,取row_count条数据作为一页(page)

这里ESfromMySQLOFFSET一样的含义,跳过多少条数据,或者叫做偏移量是多少,都是从0开始,都可以理解所有数据构成一个大数组,这个数值就是数组的角标,第一条数据是角标为0的数据。

ES中不指定from仅指定size参数表示取前size条数据;

同样的MySQL中,不指定offset参数,仅仅limit row_count则表示取前row_count条数据:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

size——

定义一页(a page)有多少个doc(对应关系型数据库的多少条数据),即pageSize(一页数据的大小)

ES的size参数与关系型数据库MySQLlimit offset, row_count语法中的row_count值是一样的,表示取多少条数据或者叫做一页数据的大小是多少。

分页——

要获取第currentPage页的数据,一页数据的个数(或条数)为pageSize个:

ES

GET index_xxx/_search
{
 "from": (currentPage-1) * pageSize,
 "size": pageSize,
 //忽略其他...
}

MySQL

offset = (currentPage-1) * pageSize

row_count = pageSize

select * from t_xxx limit (currentPage-1) * pageSize, pageSize;

ES深分页的问题

一页获取数据量太大,报错

极限一点,就从开始取一万零一条数据,报错了。

GET my-index-000001/_search
{
  "from": 0,
  "size": 10001,
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

报错:非法参数异常,结果窗口太大from+size不能超过10000

"caused_by" : {
  "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."
}

分页深度太大,报错

极限一点,pageSize=1,每页1条数据

现在获取第10001页的数据,报错了。

GET my-index-000001/_search
{
  "from": 10000,
  "size": 1,
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

报错:

   "caused_by" : {
     "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."
   }

官方解释

Avoid using from and size to page too deeply or request too many results at once. Search requests usually span multiple shards. Each shard must load its requested hits and the hits for any previous pages into memory. For deep pages or large sets of results, these operations can significantly increase memory and CPU usage, resulting in degraded performance or node failures.

官方的解释:

避免分页深度太大(获取后面的页数据的深度大于获取前边的页数据的深度),避免一次获取太多的数据。


搜索请求通常跨多个分片(因为每个主分片都会存储完整数据的一部分数据,副本分片是主分片的拷贝),


每个分片必须加载(load)请求(所需要分页数据)的数据,以及之前的数据(当前页之前的数据)到内存当中。


也就是说分页不是直接取出所取分页的数据、只获取当前页,而是需要把(from参数)跳过(skip)的数据也要取出来,然后把这些需要跳过的数据再过滤掉。实际上就是说,要把from需要跳过(skip)的数据和指定分页的数据全部拿到内存中来,然后再去除掉需要跳过(skip)的数据。


那么这个加载过程是耗内存资源的,尤其是在获取后面的分页数据且一次获取的数据量很大,比如取第1000页消耗的内存资源是比取第1页消耗的多的多,一次获取5000条比一次获取1条消耗的内存资源要多得多。


其实结合起来就是from很大,代表了深分页,size很大,代表了一次性获取数据量的大小很大,总归是加载太多数据会引发性能问题。加载from+size条数据到内存中,当from+size太大,就容易出现性能问题。


对于深分页(deep pages,分页太多,取非常靠后边的分页数据)或者取太多数据(比如一次就要取10000条数据)(乃至深分页且获取大量数据),

这些操作可能会显著增加内存和CPU的使用率,导致性能下降或节点故障。


由于from跳过的数据+要取的size个数据都会被加载到内存中,深分页和获取大量数据就会非常耗资源,既然耗资源,那就不能无止尽的获取后边的分页以及无止尽的一次性取大量数据。


由于分片需要加载到内存的数据条数是fromsize共同决定的,因此需要限制from+size

By default, you cannot use from and size to page through more than 10,000 hits. This limit is a safeguard set by the index.max_result_window index setting. If you need to page through more than 10,000 hits, use the search_after parameter instead.

默认地,ES限制了from+size不能超过一万。

这个默认值当然可以改,也提供了修改的方法。但是就如之前的分析,from+size太大会出现性能问题,因此还是不要改的好,如果确实有这样的需求需要换解决方案。

Warning:Elasticsearch uses Lucene’s internal doc IDs as tie-breakers. These internal doc IDs can be completely different across replicas of the same data. When paging search hits, you might occasionally see that documents with the same sort values are not ordered consistently.

Elasticsearch 使用 Lucene 的内部文档 ID 作为决定因素。这些内部文档 ID 在相同数据的副本之间可能完全不同。当分页搜索命中时,您有时可能会发现具有相同排序值的文档的排序不一致。

这个说明是说会为文档单独维护一个内部的id,即使相同数据的副本间,这个id也可能不同。


这样,就可能会引发一个问题:指定相同的排序参数,获取到的结果可能不一样(在指定排序的排序值一样的情况下的文档(doc)排序可能不同,有可能某doc上一次获取的结果是在前边,下一次相同参数请求获取到的doc跑到后面了。**原因就是:**指定排序参数的排序结果中,文档排序一样的话,默认会使用这个内部id排序,而不同的副本这个内部id可能不一样,于是导致排序的结果可能不一致)

这个在下面也会说明。

其他解决方案

Search after

You can use the search_after parameter to retrieve the next page of hits using a set of sort values from the previous page.

Using search_after requires multiple search requests with the same query and sort values. If a refresh occurs between these requests, the order of your results may change, causing inconsistent results across pages. To prevent this, you can create a point in time (PIT) to preserve the current index state over your searches.

可以使用search_after参数来获取下一页数据,search_after参数的值设置为前一页数据的sort值

也就是说,基于前一页的记录的sort值,来往后取数据。

使用search_after要求多次查询使用相同的query条件和排序条件(sort)。

但是,会存在一个问题,多次查询间,发生了数据添加操作(refresh会把新索引的数据(doc)会把数据从内存中的buffer写入到filesystem cache中,并清除内存buffer中的数据,这个doc就可以被检索到),那么这些查询的结果中数据的排序可能会发生变化,导致跨页数据的不一致。

为了避免上面的问题,解决跨页请求数据一致性的问题,可以创建一个pit,保存当前索引的状态。

Elasticsearch pit (point in time) is a lightweight view into the state of the data as it existed when initiated.


pit是一个在它(pit)被创建时刻数据的一个轻量级视图。

也就是说,多次请求,通过同一个pit,可以保证所见的数据视图是一致的,即使发生了数据更新(如插入,删除数据),在这些查询请求间,数据视图是一致的。

可以进行实验印证

pit创建后(pit的使用下面会说明),检索一万条

GET /_search
{
"size": 10000,
"query": {
"match": {
"title": "elasticsearch"
}
},
"sort": [
{
"id": {
  "order": "asc"
}
},
{
"_shard_doc": "asc"
}
],
"pit": {
"id": "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAAPQMWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==",
"keep_alive": "120m"
}
}

可以发现数据中存在一条数据:

{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "10",
  "_score" : null,
  "_source" : {
    "id" : "10",
    "title" : "Elasticsearch Security and Authentication",
    "content" : "Configure Elasticsearch security features like X-Pack Security for authentication and authorization."
  },
  "sort" : [
    10,
    110101
  ]
},

那现在我删除掉doc id为10的文档。

DELETE my-index-000001/_doc/10
//结果:
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "10",
"_version" : 7,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 120108,
"_primary_term" : 3
}

会发现按照刚才的查询再执行一次,还能查询到doc id为10的文档,

注意,如果不使用pit,会检索到最新的数据变动,因此,是否需要保证视图一致性,是否需要检索到最新数据变化,这个看实际需要。

在这里插入图片描述

然后现在我们再插入一个新的id为10的文档,内容和原来不一样

POST /my-index-000001/_doc/10  
{  
"id": "10",  
"title": "Elasticsearch Security and Authentication [[not same with before]] ",  
"content": "Configure Elasticsearch security features like X-Pack Security for authentication and authorization."  
}  

{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "10",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 120109,
"_primary_term" : 3
}

然后按照之前的查询条件,进行查询,结果还是之前的结果。

{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "10",
  "_score" : null,
  "_source" : {
    "id" : "10",
    "title" : "Elasticsearch Security and Authentication",
    "content" : "Configure Elasticsearch security features like X-Pack Security for authentication and authorization."
  },
  "sort" : [
    10,
    110101
  ]
},

但是,普通查询可以查到新插入的数据。

GET my-index-000001/_doc/10
//结果:
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "10",
"_version" : 1,
"_seq_no" : 120109,
"_primary_term" : 3,
"found" : true,
"_source" : {
"id" : "10",
"title" : "Elasticsearch Security and Authentication [[not same with before]] ",
"content" : "Configure Elasticsearch security features like X-Pack Security for authentication and authorization."
}
}

当然清除掉这个pit

DELETE /_pit
{
"id" : "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAAPQMWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA=="
}

新生成一个pit进行查询

POST /my-index-000001/_pit?keep_alive=10m

可以检索到新的数据。

在这里插入图片描述

通过上面的实验可以印证,使用同一个有效的未过期的pit,数据视图始终是一致的,即使之后数据发生了变动,在使用同一个pit查询,看到的视图不会变。当然清除这个pit后使用新的pit进行进行检索,可以检索到最新的数据变动。

解决两个问题

总结下:这里有两个问题,

  1. 一个是解决深分页问题,可以使用search_after;

    相比传统的from + Size分页方式,Search After接口能够更高效地定位到指定位置的数据,避免了需要跳过大量数据的问题,从而提高了查询效率。当查询达到深度分页时,使用from + Size方式的成本会变得很高,而Search After接口通过提供一个活动光标来规避此问题,使用上一页的结果来帮助检索下一页,使得查询更为高效。


    Search After接口支持实时数据更新,适用于需要及时获取数据变化的场景。

    由于Search After是基于上一页的最后一条数据来确定下一页的位置,因此在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时地反映到游标上。

  2. 一个是多次从查询间发生了数据变动的问题(需要解决请求间数据视图不一致问题),可以在查询前创建一个pit,保存当前索引状态,使用这个pit参数进行请求,就能够始终得到一个一致的数据视图。

这两个问题不要混在一块了。如果不是很在意视图不一致问题,比如读多写少,数据很少变动,那就没必要使用pit,根据实际情况来。

有没有深分页查询的必要性?

现在我们回过头来,反思下,业务上是否真的需要进行深度分页。

官方为保证ES的性能,限制 from+size 不超过10000。

我们看看看一万是个多大的存在

以百度搜索、bing搜索为例,一页数据10条,

那10000条意味着可以检索1000页,我们日常通过这些搜索引擎检索内容,几十页都不会去翻;

电子商城买东西,(以50一页看,可以检索200页)基本也不会翻几页,通常会追加条件,更精确的检索;

那就看业务上能否限制下,限制检索页数,像上面的案例200页,1000页足够检索的了,谁也不会闲的没事去点那么多页。

然后一些特殊的需要

search after & PIT的使用方式

注意1:使用search after就不要使用from跳过数据了

注意2search after不支持随机跳转分页。(可以通过记录上一页的search_after参数和当前页最后一条数据的sort,来实现上一页,下一页)

我们来举个例子:同时使用search after和pit,能够同时满足深分页,以及视图保证前后一致性(一致性视图的问题上面已经讲述,这里不再赘述,仅仅展示用法)。

1.创建pit

POST /my-index-000001/_pit?keep_alive=10m
//结果如下:得到以一个pit id
{
  "id" : "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA=="
}

2.首次查询

IMPORTANT:All PIT search requests add an implicit sort tiebreaker field called _shard_doc, which can also be provided explicitly. If you cannot use a PIT, we recommend that you include a tiebreaker field in your sort. This tiebreaker field should contain a unique value for each document. If you don’t include a tiebreaker field, your paged results could miss or duplicate hits.

重要提示:

所有 PIT 搜索请求都会添加一个名为 _shard_doc 的隐式排序仲裁字段,该字段也可以显式提供。如果您无法使用 PIT,我们建议您在排序中包含决胜局字段(tiebreaker)。此决胜局字段(tiebreaker)应包含每个文档的唯一值。如果您不包含决胜局字段(tiebreaker),则分页结果可能会丢失或重复命中。

这就是上边提到的**”会发现具有相同排序值的文档的排序不一致“**的问题。

我们指定的排序方式,结果中两个文档排序结果一样,那可以通过指定tiebreaker来保证排序的确定性,默认使用doc内部id来排,由于不同副本分片的同一数据的内部id可能不一样,会导致排序结果的不稳定性。

NOTE:Search after requests have optimizations that make them faster when the sort order is _shard_doc and total hits are not tracked. If you want to iterate over all documents regardless of the order, this is the most efficient option.

搜索请求进行了优化,当排序顺序为 _shard_doc 并且不跟踪总点hits时,搜索速度会更快。如果您想迭代所有文档而不考虑顺序,这是最有效的选择。

也就是说,不指定排序方式,使用默认的***_shard_doc***排序不关注数据总量(total)(通过查询携带带参数"track_total_hits": false),搜索速度会更加快速。

IMPORTANT:If the sort field is a date in some target data streams or indices but a date_nanos field in other targets, use the numeric_type parameter to convert the values to a single resolution and the format parameter to specify a date format for the sort field. Otherwise, Elasticsearch won’t interpret the search after parameter correctly in each request.

关于Elasticsearch中如何处理不同数据字段(特别是日期字段)在排序(sort)时的兼容性问题的指导


如果排序字段在某些目标数据流或索引中是日期,但在其他目标中是 date_nanos 字段,请使用 numeric_type 参数将值转换为单一分辨率,并使用 format 参数指定排序字段的日期格式。否则,Elasticsearch 将无法正确解释每个请求中参数后的搜索。


  • 在Elasticsearch中,日期字段可以有两种类型:datedate_nanos

  • date 类型通常使用毫秒作为时间单位来存储日期和时间。

  • date_nanos 类型则使用纳秒作为时间单位,提供更高的时间精度。

当你在进行搜索或排序操作时,如果某些数据流或索引中的 sort 字段是 date 类型,而另一些是 date_nanos 类型,那么Elasticsearch可能无法正确地解释或比较这些字段,因为它们有不同的时间单位。


解决方式:


  • 使用 numeric_type 参数:这个参数允许你将日期值转换为统一的分辨率。这样,无论原始字段是 date 还是 date_nanos 类型,排序操作都可以基于相同的分辨率进行。
  • 使用 format 参数:这个参数允许你指定日期格式。这确保了在排序时,所有日期值都按照指定的格式进行解析和比较。

重要性:


  • 如果不采取上述措施,Elasticsearch在每次请求时可能无法正确解释排序参数,从而导致排序结果不准确或不符合预期。

不带search_after参数,search_after依赖于上一次查询结果。

注意使用pit,请求路径中就不需要就不需要带index

GET /_search
{
  "size": 10000,
  "query": {
    "match": {
      "title": "elasticsearch"
    }
  },
  "sort": [
    {
      "id": {
        "order": "asc"
      }
    },
    {
      "_shard_doc": "asc"   // <1>
    }
  ],
  "pit": {
    "id": "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==", //<2>
    "keep_alive": "120m"  //<3>
  }
}

<1>使用显示的 _shard_doc 升序平局处理(tiebreak )对搜索结果进行排序。

<2>PIT ID for the search.

The search response includes an array of sort values for each hit. If you used a PIT, a tiebreaker is included as the last sort values for each hit. This tiebreaker called _shard_doc is added automatically on every search requests that use a PIT. The _shard_doc value is the combination of the shard index within the PIT and the Lucene’s internal doc ID, it is unique per document and constant within a PIT. You can also add the tiebreaker explicitly in the search request to customize the order

_shard_doc 值是 PIT 中的分片索引和 Lucene 的内部文档 ID 的组合,它对于每个文档都是唯一的,并且在 PIT 中是恒定的。因此,可以在搜索请求中显式添加tiebreaker以自定义顺序。

<3>You can repeat this process to get additional pages of results. If using a PIT, you can extend the PIT’s retention period using the keep_alive parameter of each search request.

可以使用每个搜索请求的 keep_alive 参数来延长 PIT 的保留期

可指定"track_total_hits": false参数, Disable the tracking of total hits,进一步加快分页速度。

结果:

{
  "pit_id" : "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==",  //<1>
  "took" : 983,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10000,
      "relation" : "gte"
    },
    "max_score" : null,
    "hits" : [
      //忽略前面的9999条数据,直接看最后这条
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "10000",
        "_score" : null,
        "_source" : {
          "id" : 10000,
          "title" : "Elasticsearch Performance Tuning",
          "content" : "Replicate indices across multiple Elasticsearch clusters for data redundancy and disaster recovery."
        },
        "sort" : [   //<2>
          10000,
          77050   //<3>
        ]
      }           
    ]
  }
}

<1>更新了的pit_id

<2> Sort values for the last returned hit. (返回的命中值最后一个文档的sort )

<3>The tiebreaker value, unique per document within the pit_id.(决胜局值(tiebreaker),pit_id 内每个文档都是唯一的。)

在这里插入图片描述

3.之后的查询

下一次查询时候要把上一次请求结果最后一条数据的pit_idsort带过来,分别传到pit.id参数和search_after(数组格式)参数

GET /_search
{
  "size": 10000,
  "query": {
    "match": {
      "title": "elasticsearch"
    }
  },
  "sort": [
    {
      "id": {
        "order": "asc"
      }
    },
    {
      "_shard_doc": "asc"
    }
  ],
  "pit": {
    "id": "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==",  //<1>
    "keep_alive": "120m"  //<4>
  },
  "search_after": [ //<2>
    10000,    
    77050     //<3>
  ]
}

<1>根据上次请求结果中的pit_id,更新请求中的pit.id参数,

<2>上一次查询结果命中的文档中最后一个的sort,注意是数组格式

<3>The tiebreaker value, unique per document within the pit_id.

<4>设置keep_alive延长pit的过期时间,m是分钟,这里的实验设置的有点长

结果

{
  "pit_id" : "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==",
  "took" : 1070,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },  
  "hits" : {
    "max_score" : null,
    "hits" :[
        //省略9999个doc
       {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "20000",
        "_score" : null,
        "_source" : {
          "id" : 20000,
          "title" : "Elasticsearch Data Ingestion",
          "content" : "Build beautiful visualizations and dashboards with Kibana for your Elasticsearch data."
        },
        "sort" : [
          20000,
          66357
        ]
      }
    ]
  }
}

之后的查询继续步骤3即可。

延伸

注意:由此可见分页已经可以搜索到10000之后,

但是注意,size是不能大于10000,如上面的查询改成size:10001,则报错

      "caused_by" : {
        "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."
      }

原因不再赘述,上面已经分析过。

4.清除pit

当不再使用这个pit,需要清除掉,或者等待它自动过期失效,自动清除掉。

手动清除如下:

DELETE /_pit
{
    "id" : "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA=="
}
//结果如下:删除成功
{
  "succeeded" : true,
  "num_freed" : 1
}

滚动搜索|Scroll search results

We no longer recommend using the scroll API for deep pagination. If you need to preserve the index state while paging through more than 10,000 hits, use the search_after parameter with a point in time (PIT).

官方不再建议使用滚动 API 进行深度分页。

如果需要在分页超过 10,000 个命中时保留索引状态,建议使用带有时间点 (PIT) 的 search_after 参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/722087.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Opencv高级图像处理

文章目录 Opencv高级图像处理图像坐标二值化滤波高斯滤波中值滤波 开闭运算检测霍夫圆检测边缘检测Canny边缘检测findContours区别傅里叶变换-高/低通滤波 直线检测 相机标定视频处理视频格式 模板摄像头处理&#xff08;带参调节&#xff09;单图片处理&#xff08;带参调节&a…

JAVA上门家政服务系统源码微信小程序+微信公众号+APP+H5

&#x1f3e0;家政服务系统&#xff1a;一键预约&#xff0c;轻松享受家居生活&#x1f389; 功能介绍 用户端&#xff1a;精准分类、支持家政、维修、万能服务、一口价、报价、线上、各类家政服务、优惠专区、师傅入驻、商家入驻、我的需求、补费明细、我的投诉 师傅端&…

基于Spring Boot+VUE旧物置换网站

1前台首页功能模块 旧物置换网站&#xff0c;在系统首页可以查看首页、旧物信息、网站公告、个人中心、后台管理等内容&#xff0c;如图1所示。 图1系统功能界面图 用户注册&#xff0c;在用户注册页面通过填写用户名、密码、姓名、性别、头像、手机、邮箱等内容进行用户注册&…

Linux 系统图像化编程GTK入门

环境前期准备 演示环境&#xff1a;Windows 11 Ubuntu 22.04.4 VS Code 前提条件&#xff1a;1、Windows 11 子系统Ubuntu 22.04.4 已经安装图形化界面&#xff0c;如果没有安装请参考文章&#xff1a; windows11子系统Ubuntu 22.04.4子安装图形化界面 2、Ubuntu 22.04.4…

小程序餐饮点餐系统,扫码下单点菜,消费端+配送端+收银端+理端

目录 前言&#xff1a; 一、小程序功能有哪些 前端&#xff1a; 管理端&#xff1a; 二、实体店做小程序的好处 方便快捷的点餐和支付体验&#xff1a; 扩大店铺的曝光度和影响力&#xff1a; 优化顾客体验和服务质量&#xff1a; 降低成本和提高效率&#xff1a; 数据…

iview 组件里面的(任何一个月)整月日期全部选中_iview时间轴选中有历史记录日期

iview 组件里面的整月日期全部选中&#xff1a; ①&#xff1a;第一种是当前月的日期全部选中&#xff1a; 先上效果图&#xff1a;当前月分 获取到的值&#xff1a; 当前月的方法&#xff1a; // getDateStr() {// var curDate new Date();// var curMonth curDate.ge…

K8s的资源对象

资源对象是 K8s 提供的一些管理和运行应用容器的各种对象和组件。 Pod 资源是 K8s 中的基本部署单元&#xff0c;K8s通过Pod来运行业务应用的容器镜像 Job 和 CronJob 资源用于执行任务和定时任务&#xff0c;DaemonSet 资源提供类似每个节点上守护进程&#xff0c; Deployment…

WPF 深入理解四、样式

样式 WPF中的各类控件元素,都可以自由的设置其样式。 诸如: 字体(FontFamily) 字体大小(FontSize) 背景颜色(Background) 字体颜色(Foreground) 边距(Margin) 水平位置(HorizontalAlignment) 垂直位置(VerticalAlignment)等等。 而样式则是组织和重用以上的重要工具。不是使…

Nginx缓存之web缓存配置

Web 缓存可节约网络带宽&#xff0c;有效提高用户打开网站的速度。由于应用服务器被请求次数的降低&#xff0c;也相对使它的稳定性得到了提升。Web 缓存从数据内容传输的方向分为前向位置缓存和反向位置缓存两类。如下图所示。 前向位置缓存既可以是用户的客户端浏览器&#x…

iOS 18 Siri 升级之后都有哪些改变?

新界面 首先最显著的改变就是 Siri 的界面不同了&#xff0c;之前的界面是在打开 Siri 之后会出现一个圆形图案&#xff0c;而在 Siri 升级之后变成了屏幕边缘发出亮光。 来源&#xff1a;Apple 可在任意位置使用 苹果的生成式人工智能 Apple Intelligence 将为 Siri 提供支…

【前端】 nvm安装管理多版本node、 npm install失败解决方式

【问题】If you believe this might be a permissions issue, please double-check the npm ERR! permissio或者Error: EPERM: operation not permitted, VScode中npm install或cnpm install报错 简单总结&#xff0c;我们运行npm install 无法安装吧包&#xff0c;提示权限问题…

pdf怎么压缩到2m以内或5m以内的方法

PDF作为一种广泛使用的文档格式&#xff0c;已经成为我们工作和生活中不可或缺的一部分。然而&#xff0c;有时候PDF文件内存会比较大&#xff0c;给我们的存储和传输带来了很大的不便。因此&#xff0c;学会压缩 PDF 文件是非常必要的。 打开"轻云处理pdf官网"&…

JAVA二手车交易二手车市场系统源码支持微信小程序+微信公众号+H5+APP

&#x1f697;二手车交易系统小程序&#xff1a;让买卖更轻松&#x1f50d; 功能介绍 我的粉丝、我的关注、获赞、访客 我的动态、认证中心、我的团队、开通会员 免费估值、买二手车、我要卖车、车型选择 每日上新、底价专区、精准筛选、附近展厅商 车辆的详细信息、拨打电…

Mamba: Linear-Time Sequence Modeling with Selective State Spaces论文笔记

文章目录 Mamba: Linear-Time Sequence Modeling with Selective State Spaces摘要引言 相关工作(SSMs)离散化计算线性时间不变性(LTI)结构和尺寸一般状态空间模型SSMs架构S4(补充)离散数据的连续化: 基于零阶保持技术做连续化并采样循环结构表示: 方便快速推理卷积结构表示: 方…

从0开始开发一个简单web界面的学习笔记(HTML类)

文章目录 什么是HTML页面vscode 开放工具搭建第一个HTML页面编写vscode 如何快速生成代码框架html标签——注释、标题、段落、换行标签格式化标签img 标签(src 属性01)img 属性02(alt、title、width/height、border)a标签href属性a标签target属性表格标签01 基本属性表格标签02…

镜头跟踪的两种方法

方法一 (1) 原理&#xff1a;使球与摄像机保持固定的角度和距离 (2) 给Main Camera添加CamraCtrller.cs组件 public Transform Player;//小球的Transformprivate Vector3 offset;//小球与摄像机位置的偏移&#xff08;在三轴上的距离&#xff09;void Start(){offset Playe…

【LinkedList与链表】

目录 1&#xff0c;ArrayList的缺陷 2&#xff0c;链表 2.1 链表的概念及结构 2.2 链表的实现 2.2.1 无头单向非循环链表实现 3&#xff0c;LinkedList的模拟实现 3.1 无头双向链表实现 4&#xff0c;LinkedList的使用 4.1 什么是LinkedList 4.2 LinkedList的使用 5…

next.js v14 升级全步骤|迁移 pages Router 到 App Router

【概括】本文升级整体按照官网文档指引进行&#xff0c;在迁移 pages Router 前先看了官网的实操视频。 【注意】文章内对 .babel.ts、next.config.js 进行了多次更改&#xff0c;最终配置可见 报错3: Server Error ReferenceError: React is not defined 一、升级 Next.js 版…

基于Spark3.3.4版本,实现Standalone 模式高可用集群部署

目录 一、环境描述 二、部署Spark 节点 2.1 下载资源包 2.2 解压 2.3 配置 2.3.1 配置环境变量 2.3.2 修改workers配置文件 2.3.3 修改spark.env.sh文件 2.3.4 修改spark-defaults.conf 2.4 分发 2.5 启动服务 2.5.1 启动zookeeper 2.5.2 启动hdfs 2.5.3 启动spar…

20240611-WWDC2024-visionOS 2/Apple Intelligence/ARKit

目录 1 visionOS 2 1&#xff09;从2D图像提取左右眼的视角&#xff0c;生成空间照片——利用机器学习 2&#xff09;提供丰富的API和框架 2 Apple Intelligence 1&#xff09;自动对通知优先级排序、缩略通知、专注模式 2&#xff09;Siri可以根据屏幕内容执行相关操作 …