elasticsearch 深度分页查询 Search_after(图文教程)

Search_after使用

    • 一. 简介
    • 二. 不带PIT的search_after查询
      • 2.1 构造数据
      • 2.2 search_after分页查询
      • 2.2 问题
    • 三. 带PIT的search_after查询
      • 3.1 构建第一次查询条件
      • 3.2 进行下一页查询
      • 3.3 删除PIT
    • 四.参考文章

前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。
作者:神的孩子都在歌唱

一. 简介

search_after 是 Elasticsearch 提供的一种分页查询方式,它可以用来在已经排序的结果集中进行分页查询。

search_after查询步骤如下(下面有具体的例子帮助理解):

image-20240306154454909

最后一条排序结果相当于它的游标

优点:

  1. 性能优势: 相对于传统的 fromsize 参数来说,search_after 在处理大量数据时性能更好,因为它不需要跳过之前的结果集,不严格受制于 max_result_window,可以无限制往后翻页。 fromsize只能翻页10000条.
  2. 适用于实时数据: 在实时数据更新频繁的场景下,search_after 可以确保查询结果的准确性,因为它不会受到新数据插入的影响。
  3. 避免深度分页问题: 使用 search_after 可以避免深度分页问题,即当页数很大时,传统的分页方式性能会下降。

缺点:

  1. 需要结果排序: 使用 search_after 前需要对结果集进行排序,如果排序字段较多或者数据量较大,可能会影响性能。
  2. 只适用于唯一排序字段: search_after 只支持基于唯一排序字段的分页查询,如果有多个排序字段,需要确保排序字段的唯一性。
  3. 不支持随机访问: 由于 search_after 是基于上一页的最后一个文档进行分页,所以不支持随机访问,只能逐页查询。

使用场景:

  1. 大数据量分页查询: 当需要处理大量数据并进行分页查询时,search_after 可以提供更好的性能。
  2. 实时数据展示: 在实时数据展示的场景下,可以使用 search_after 来确保查询结果的准确性。
  3. 避免深度分页问题: 当需要避免深度分页问题时,可以考虑使用 search_after 来提高查询效率。

官方文档说明不再建议使用scroll滚动分页和from size分页,建议使用search_after

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 参数。

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.

默认情况下,您不能使用fromsize翻阅超过 10,000 个点击。该限制是由索引设置设置的保障措施 index.max_result_window。如果您需要翻阅超过 10,000 个点击,请使用search_after 参数代替。

二. 不带PIT的search_after查询

建议带PIT,我举的这个列子是帮助理解PIT的作用

2.1 构造数据

PUT /test/_bulk?refresh
{"index":{}}
{"name": "小狗", "leg": 4, "iswing": false}
{"index":{}}
{"name": "小鸡", "leg": 2, "iswing": true}
{"index":{}}
{"name": "小猫", "leg": 4, "iswing": false}

2.2 search_after分页查询

注意:当我们使用search_after时,from值必须设置为0或者-1。

首先我们通过排序查询10条数据

GET /test/_search
{
  "size": 10, 
  "sort": [
    {
      "name.keyword": {
        "order": "desc" // 对返回的值进行排序
      }
    }
  ]
}

image-20240306104332631

要获取下一页结果,需要使用最后一条文档的排序值(也就是sort列表里面的值) 作为 search_after 参数重新运行上一个搜索。

GET test/_search
{
  "size": 10, 
  "search_after": ["小鸡"],
  "sort": [
    {
      "name.keyword": {
        "order": "desc"
      }
    }
  ]
}

这样子他就会从排序好的name为小猫开始查询

image-20240306104738671

2.2 问题

  1. 每次检索新的结果页时更新数组,重复此过程。如果这些请求之间发生刷新,结果的顺序可能会发生变化,从而导致页面之间的结果不一致。为了防止这种情况,您可以创建一个时间点 (PIT) 来在搜索中保留当前索引状态。

  2. 排序的值不唯一,翻页的时候文档对应不上。为了防止这种情况,PIT 搜索请求都会添加一个名为 _shard_doc 的隐式排序字段,该字段也可以显式提供,这个字段在es中叫做 tiebreaker 。此字段包含每个文档的唯一值。如果您不包含tiebreaker字段,则分页结果可能会丢失或重复命中。

比如我在插入一只小鸟

PUT /test/_bulk?refresh
{"index":{}}
{"name": "小鸟", "leg": 2, "iswing": true}

在执行查询语句

GET test/_search
{
  "size": 10, 
  "search_after": ["小鸡"],
  "sort": [
    {
      "name.keyword": {
        "order": "desc"
      }
    }
  ]
}

可以看到查询的结果发生了变化,并且第11条应该还是小鸡而不是小鸟

image-20240306105632872

为了解决这种情况,es在7.x引入了PIT的概念,它相当于是 存储索引数据状态的轻量级视图。

三. 带PIT的search_after查询

一些关于PIT的知识:

PIT的快照时间点: 创建 PIT 时记录的是索引状态的快照,而不是实时数据。即使 PIT 不过期,它也只反映创建 PIT 时的索引状态,而不包括之后新增的数据。

数据更新延迟: 即使使用 PIT 进行查询,由于数据写入和索引过程中可能存在一定的延迟,新数据可能不会立即反映在查询结果中。这种延迟可能导致查询结果不是实时的。

实时性需求: 如果需要实时性较高的查询结果,可能需要结合其他机制或策略来确保数据的实时性,如定时刷新 PIT、定时重新创建 PIT 等。

PIT对于翻页的作用:PIT确保了在后续翻页的过程中,可能会有新数据写入等操作,但这些操作不会对原有结果集构成影响,保障数据的一致性。

关于 pit的官方文档

3.1 构建第一次查询条件

POST /test/_pit?keep_alive=1m

keep_alive必须要加上,它表示这个pit能存在多久,这里设置的是1分钟

image-20240306140218461

构建第一次查询条件

GET /_search
{
  "size": 10,
  "pit": {
    "id": "z9_qAwELdGVzdC0wMDAwMDQWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAWWGlMYTRUQ2VUaE9PVlJHNzRTdHBVdwAAAAAAAAauuRZ3bEkwVkx1MlR6YVlsMUZ4MHpUV05nAAEWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAA",
    "keep_alive":"1m"
  },
   "sort": [
    {
      "name.keyword": {
        "order": "desc"
      }
    }
  ]
}

输出值如下

image-20240306135240804

我上面展示的是最后一条文档,可以看到排序sort中莫名多了个28 ,这在es官方文档中叫做tiebreaker ,官方文档中解释如下

如果您使用 PIT,tiebreaker 是 隐含的排序值,是基于_shard_doc 的升序排序方式。 _shard_doc 值是 PIT 中的分片索引和 Lucene 的内部文档 ID 的组合,它对于每个文档都是唯一的 。您还可以在搜索请求中手动添加 tiebreaker 以自定义顺序:

网上解释:tiebreaker (决胜字段),tiebreaker 等价于_shard_doc。tiebreaker 本质是每个文档的唯一值,确保分页不会丢失或者分页结果数据出现重复(相同页重复或跨页重复)。

可以在sort里面加上_shard_doc 进行自定义排序

"sort": [
{
  "name.keyword": {
    "order": "desc"
  },
  "_shard_doc": "asc"
}

3.2 进行下一页查询

我们在拿它sort里面的值放入到search_after中进行下一页查询

在每个搜索请求中添加 keep_alive 参数来延长 PIT 的保留期,相当于是重置了一下时间

GET /_search
{
  "size": 10,
  "pit": {
    "id": "z9_qAwELdGVzdC0wMDAwMDQWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAWWGlMYTRUQ2VUaE9PVlJHNzRTdHBVdwAAAAAAAAauuRZ3bEkwVkx1MlR6YVlsMUZ4MHpUV05nAAEWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAA",
    "keep_alive":"1m"
  },
   "sort": [
    {
      "name.keyword": {
        "order": "desc"
      }
    }
  ],
  "search_after": [
      "小鸡",
      28
  ],
  "track_total_hits": false     // 禁用总点击率跟踪以加快分页速度     
}

通过以下输出可以看到。我们已经成功进入到下一页了

image-20240306135630489

这样子就能够成功进行分页查询了

3.3 删除PIT

完成后,您应该删除您的 PIT。

DELETE /_pit
{
    "id" : "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
}

四.参考文章

https://blog.csdn.net/qq_26857259/article/details/134372438

https://blog.csdn.net/yangbindxj/article/details/123979413 有上一页方案

作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。

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

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

相关文章

【JS】APIs:事件流、事件委托、其他事件、页面尺寸、日期对象与节点操作

1 事件流 捕获阶段&#xff1a;从父到子 冒泡阶段&#xff1a;从子到父 1.1 事件捕获 <body> <div class"fa"><div class"son"></div> </div> <script>const fadocument.querySelector(.fa);const sondocument.qu…

指针----三

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1.冒泡排序2、二级指针3.指针数组4.指针数组模拟二级指针5.字符指针变量6.数组指针变量6.1 数组指针变量是什么&#xff1f;2.2 数组指针变量的初始化 前言 下…

bug总结(1)--变量取错

a c t i v i t y [ ′ t a g n a m e ′ ] 应为 activity[tag_name]应为 activity[′tagn​ame′]应为couponActivitList[0][‘name’] .隐藏的bug&#xff0c;在测试中竟然测不出来&#xff0c;而且上线了好久。为啥会出现这种低级错误呢&#xff1f;第一是写的时候不够仔细认…

【Python数据结构与判断2/7】数据和判断小结

目录 序言 print() 变量 赋值 四种数据类型 字符串 格式化输出 四则运算 取整与取模 比较运算 逻辑运算 判断 if语句 if-else语句 if-elif-else语句 Tips 空值、0、非0非空值 实战案例 输入密码 短信模板 总结 序言 今天将对前面学过的内容进行一个复习小结…

如何从碎屏的华为手机恢复数据?6 种热门方法

“只是想知道是否可以从屏幕损坏的华为恢复数据&#xff1f;我尝试将其插入我的笔记本电脑&#xff0c;但手机不允许我进入&#xff0c;因为它要求我更改手机中的设置等.我最好的选择是什么&#xff1f; 当发生事故&#xff0c;我们的华为手机屏幕损坏时&#xff0c;访问这些关…

【数据分享】2000-2022年全国1km分辨率的逐月PM10栅格数据(免费获取)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2022年全国范围逐月的PM2.5栅格数据、2013-2022年全国范围逐月SO2栅格数据和2013-2022年全国范围逐月CO栅格数据&#xff08;可以查看之前的文章获悉详情&#xff09;&#xff01; 本次我们…

云原生(一)、linux快速上手

Linux是一种开源的Unix-like操作系统内核。它是由Linus Torvalds于1991年首次发布&#xff0c;其后经过全球的自由软件社区的持续开发和改进。Linux内核是操作系统的核心部分&#xff0c;但通常与GNU项目合作&#xff0c;以形成完整的操作系统&#xff0c;被称为Linux发行版&am…

力扣hot100:152.乘积最大子数组(动态规划)

一个子数组问题&#xff0c;我们要使用线性dp&#xff0c;最好先考虑以i结尾&#xff0c;如果定义dp[i]为前i个数最大子数组乘积值 那么dp[i-1]就无法转移到dp[i]。因此我们先考虑dp[i]定义为以第i个数结尾的最大子数组乘积值。 53. 最大子数组和 最大子数组和是一个动态规划问…

b树(一篇文章带你 理解 )

目录 一、引言 二、B树的基本定义 三、B树的性质与操作 1 查找操作 2 插入操作 3 删除操作 四、B树的应用场景 1 数据库索引 2 文件系统 3 网络路由表 五、哪些数据库系统不使用B树进行索引 1 列式数据库 2 图形数据库 3 内存数据库 4 NoSQL数据库 5 分布式数据…

小巧设备,大能量:探索口袋中的远程控制神器

在这个科技日新月异的时代&#xff0c;我们的生活被各种手机软件所包围。几乎每个人都有一个甚至多个手机&#xff0c;你是否也有遇到过需要远程操作自己某一台手机的场景呢&#xff1f;今天&#xff0c;我要向大家推荐一款神奇的手机远程操作神器&#xff0c;让你可以随时随地…

Cocos2dx-lua ScrollView[二]进阶篇

一.概述 本文缩写说明:sv = ScrollView, item代表ScrollView的一个子节点 如果对sv熟系程度还不够,请阅读基础篇: Cocos2dx-lua ScrollView[一]基础篇-CSDN博客 本文介绍sv的一种封装类库,来实现快速创建sv,有如下几个优点: 1.item的位置通过参数控制,提高开发效率…

virtualbox下centos安装增强工具没反应

virtualbox下centos安装增强工具没反应 标签:linux 可能原因猜想 virtualbox下最小化安装CentOS&#xff0c;由于最小化安装时&#xff0c;没有选择Development Tools组&#xff0c;导致没有kernel-devel&#xff0c;而后安装的kernel-devel与kernel版本不一致&#xff0c;导…

【linux进程信号】信号的产生

【Linux进程信号】信号的产生 目录 【Linux进程信号】信号的产生信号概念生活中的信号技术应用角度的信号注意信号概念用kill -l命令可以察看系统定义的信号列表信号处理常见方式概览 产生信号通过终端按键产生信号调用系统函数向进程发信号由软件条件产生信号由硬件异常产生信…

基于java(springboot+mybatis)汽车信息管理系统设计和实现以及文档

基于java(springbootmybatis)汽车信息管理系统设计和实现以及文档 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐…

【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

Vue ECharts line3D点击空白处重置图表视角- 附完整示例

ECharts&#xff1a;一个基于 JavaScript 的开源可视化图表库。 目录 效果 一、介绍 1、官方文档&#xff1a;Apache ECharts 2、官方示例 二、准备工作 1、安装依赖包 2、示例版本 三、使用步骤 1、在单页面引入 echarts 2、指定容器并设置容器宽高 3、数据处理&…

mysql 优化——磁盘空间优化

前言 有的时候&#xff0c;表的数据太多&#xff0c;为了提高查询以及存储&#xff0c;就把历史数据放到一个历史表里&#xff0c;在把历史数据删除&#xff0c;发现虽然历史数据删除&#xff0c;表的大小并没有发生改变。 Innodb 表有两部分&#xff0c;即&#xff1a;表结构…

【Emgu CV教程】9.1、形态学常用操作之腐蚀

文章目录 一、相关概念1.什么叫形态学2.形态学操作的目的3.形态学都包含哪些操作4.结构元素StructuringElement 二、腐蚀1.什么叫腐蚀2.腐蚀的作用3.腐蚀的函数 三、演示1.原始素材2.代码3.运行结果 一、相关概念 1.什么叫形态学 形态学&#xff0c;英文名称morphology&#…

【C++】了解一下STL

个人主页 &#xff1a; zxctscl 如有转载请先通知 STL 1. 什么是STL2. STL的版本3. STL的六大组件4. STL的重要性5. 如何学习STL6. STL的缺陷 1. 什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件…

C语言:基于单链表实现的泊车管理系统

一、需求 &#xff08;1&#xff09;管理员方账号登录&#xff1b; &#xff08;2&#xff09;车位管理显示&#xff1a;车位状态&#xff1b; &#xff08;3&#xff09;收费管理&#xff1a;小轿车 5元/小时&#xff0c;面包车6元/小时&#xff0c;大货车或客车7元/小时&a…