Elasticsearch检索之三:官方推荐方案search_after检索实现(golang)

Elasticsearch8.17.0在mac上的安装

Kibana8.17.0在mac上的安装

Elasticsearch检索方案之一:使用from+size实现分页

快速掌握Elasticsearch检索之二:滚动查询(scrool)获取全量数据(golang)

1、search_after检索

在前面的文章介绍了from+size的普通分页查询,以及scroll滚动查询获取全量数据,其弥补了from+size只能检索1W条以内的数据的缺憾,但是滚动查询本身也存在缺陷,当es滚动上下文大于500,则无法再次进行检索,此时search_after应运而生,它是带着使命来的。

2、使用Kibana了解search_after使用方法

说明:本地es中的数据共11000条,doc_id字段从1-11000,方便说明问题。

首先构造一个排序查询:

GET /new_tag_202411/_search
{"size": 10,"sort": [{"doc_id": {"order": "asc"}}]
}

这个检索请求发出后,返回的数据【doc_id】从1开始,每次10条,也就是返回doc_id从1-10的数据,这里着重列出返回的第10条数据:

为什么列出第10条数据,因此search_after需要第10条(检索出的最后一条)数据的sort字段的值作为输入:

GET /new_tag_202411/_search
{"size": 10,"sort": [{"doc_id": {"order": "asc"}}],"search_after": [10] // 将第一个检索请求返回的sort字段的值放入此字段
}

这时,检索返回将从doc_id为11的数据开始返回:

 

之后再将本次返回的最后一条数据sort字段放入下一次的检索条件中,继续下一次的检索,从此周而复始,直到检索完全部数据,这个逻辑和scroll滚动查询替换scroll_id的道理是一样的。

注意,使用search_after进行查询时,from必须设置为0或者-1,否则会报错:

3、esbuilder自研dsl库支持search_after字段

我自己开发的esbuilder库之前没有支持search_after字段,因为之前不知道这个功能😄😄,库地址:

github.com/liupengh3c/esbuilder

search_after字段为一个数组,数组类型都为常规的整形、字符串,相对来说比较简单,因此在dsl结构体中直接增加该字段:

type dsl struct {QueryDsl    query    `json:"query"`Source      []string `json:"_source,omitempty"`Size        int64    `json:"size,omitempty"`From        int64    `json:"from,omitempty"`OrderItems  []query  `json:"sort,omitempty"`TrackTotal  bool     `json:"track_total_hits,omitempty"`SearchAfter []any    `json:"search_after,omitempty"`
}

之后实现reciver method,支持对该字段进行赋值:

func (dsl *dsl) SetSearchAfter(searchAfter []any) *dsl {dsl.SearchAfter = searchAfterreturn dsl
}

本小节的内容与search_after的使用关系不大,看不明白也没关系,可以跳过,如果想了解的话可以留言,看到后我一定会第一时间回复。

4、利用search_after全量检索的代码实现(golang)

第一步构造一个带有排序的检索请求,排序的字段最好是每个文档的值唯一:

第二步,设计死循环进行查询,同时获取每次检索结果最后一条sort字段的值赋值给search_after字段,直接检索出所有数据:

for {fmt.Println(dslQuery.BuildJson())search := esapi.SearchRequest{Index: []string{"new_tag_202411"},Body:  strings.NewReader(dslQuery.BuildJson()),}resp, err = search.Do(context.Background(), client)if err != nil {fmt.Println("search err:", err.Error())return}err = json.NewDecoder(resp.Body).Decode(&docs)if err != nil {fmt.Println("decode err:", err.Error())return}if len(docs.Hits.Hits) == 0 {fmt.Println("no more data")break}fmt.Println("检索数据数量:", len(docs.Hits.Hits), "doc_id:", docs.Hits.Hits[len(docs.Hits.Hits)-1].Source["doc_id"])dslQuery.SetSearchAfter(docs.Hits.Hits[len(docs.Hits.Hits)-1].Sort)
}

其中,最重要的一行代码:

dslQuery.SetSearchAfter(docs.Hits.Hits[len(docs.Hits.Hits)-1].Sort)

这行代码是在每轮次中更新search_after参数,否则无法实现滚动查询的效果,无法检索全量数据。

为了方便观察,我们将size设置为1000,每次检索1000条,增加打印dsl语句以及检索到数据量、doc_id值:

从上面的打印可以看到,search_after的值一直在更新,这样才能达到检索全量的目标,doc_id值的变化也可以从侧面看出整个全量检索的过程,目标达成啦~~~~~。

5、全部实例代码

github地址:

https://github.com/liupengh3c/career/blob/main/elastic/search_after/main.go

代码:

package main
import ("context""fmt""os""strings""time""github.com/elastic/go-elasticsearch/v7/esapi""github.com/elastic/go-elasticsearch/v8"jsoniter "github.com/json-iterator/go""github.com/liupengh3c/esbuilder"
)
// 最外层数据结构
type Documents struct {Shards   Shards      `json:"_shards"`Hits     HitOutLayer `json:"hits"`TimedOut bool        `json:"timed_out"`Took     int         `json:"took"`
}
type Shards struct {Failed     int `json:"failed"`Skipped    int `json:"skipped"`Successful int `json:"successful"`Total      int `json:"total"`
}
type HitOutLayer struct {Hits     []Hits  `json:"hits"`MaxScore float64 `json:"max_score"`Total    Total   `json:"total"`
}
type Hits struct {ID     string         `json:"_id"`Index  string         `json:"_index"`Score  float64        `json:"_score"`Source map[string]any `json:"_source"`Type   string         `json:"_type"`Sort   []any          `json:"sort"`
}
type Total struct {Relation string `json:"relation"`Value    int    `json:"value"`
}
func main() {SearchFromSize()
}
func SearchFromSize() {st := time.Now()defer func() {fmt.Println("cost:", time.Since(st).Milliseconds(), "ms")}()var json = jsoniter.ConfigCompatibleWithStandardLibrarydocs := Documents{}cert, _ := os.ReadFile("/Users/liupeng/Documents/study/elasticsearch-8.17.0/config/certs/http_ca.crt")client, err := elasticsearch.NewClient(elasticsearch.Config{Username:  "elastic",Password:  "xpE4DQGWE9bCkoj7WXYE",Addresses: []string{"https://127.0.0.1:9200"},CACert:    cert,})if err != nil {fmt.Println("create client err:", err.Error())return}dslQuery := esbuilder.NewDsl()boolQuery := esbuilder.NewBoolQuery()boolQuery.Filter(esbuilder.NewRangeQuery("doc_id").Gte(1))dslQuery.SetQuery(boolQuery)dslQuery.SetFrom(0)dslQuery.SetSize(1000)dslQuery.SetOrder(esbuilder.NewSortQuery("doc_id", "asc"))dsl := dslQuery.BuildJson()search := esapi.SearchRequest{Index: []string{"new_tag_202411"},Body:  strings.NewReader(dsl),}resp, err := search.Do(context.Background(), client)if err != nil {fmt.Println("search err:", err.Error())return}err = json.NewDecoder(resp.Body).Decode(&docs)if err != nil {fmt.Println("decode err:", err.Error())return}fmt.Println(docs.Hits.Hits[len(docs.Hits.Hits)-1].Sort)dslQuery.SetSearchAfter(docs.Hits.Hits[len(docs.Hits.Hits)-1].Sort)for {fmt.Println(dslQuery.BuildJson())search := esapi.SearchRequest{Index: []string{"new_tag_202411"},Body:  strings.NewReader(dslQuery.BuildJson()),}resp, err = search.Do(context.Background(), client)if err != nil {fmt.Println("search err:", err.Error())return}err = json.NewDecoder(resp.Body).Decode(&docs)if err != nil {fmt.Println("decode err:", err.Error())return}if len(docs.Hits.Hits) == 0 {fmt.Println("no more data")break}fmt.Println("检索数据数量:", len(docs.Hits.Hits), "doc_id:", docs.Hits.Hits[len(docs.Hits.Hits)-1].Source["doc_id"])dslQuery.SetSearchAfter(docs.Hits.Hits[len(docs.Hits.Hits)-1].Sort)}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小程序基础 —— 10 如何调试小程序代码

如何调试小程序代码 在进行项目开发的时候,不可避免需要进行调试,那么如何调试小程序呢? 打开微信开发者工具后,有一个模拟器,通过模拟器能够实时预览自己写的页面,如下: 在上部工具栏中有一个…

VLM和VLAM(VLA)相关介绍和发展历程

目录 一、个人感想二、相关介绍2.1 视觉语言模型 (VLM) 的发展历程2.2 视觉语言动作模型 (VLA) 的发展历程2.3 一些关键的研究工作:一些架构图 三、发展历程3.1 视觉语言模型 (VLM) 的发展时间线3.2 视觉语言动作模型 (VLA) 的发展时间线 四、参考资料 一、个人感想…

算法题(18):删除有序数组中的重复项2

审题: 需要原地删除数据让数组中一个数据只能出现最多2次,并返回修改后的数组的数据个数 (不会有空数组情况) 思路: 双指针:我们用left指向下一个需要插入数据的位置,right去遍历数组 left数据的…

IPv6 基础协议-NDP

IPv6 基础协议报文 何为基础协议?像v4中的icmp、arp、hdcp之类的 在v6中只需要NDP协议,他是通过ICMPv6报文完成的,她能够实现邻居发现、无状态地址检测、重复地址检测、PMTU等功能 RS(133)RA(134&#x…

MySQL外键类型与应用场景总结:优缺点一目了然

前言: MySQL的外键简介:在 MySQL 中,外键 (Foreign Key) 用于建立和强制表之间的关联,确保数据的一致性和完整性。外键的作用主要是限制和维护引用完整性 (Referential Integrity)。 主要体现在引用操作发生变化时的处理方式&…

分布式事务入门 一

分布式事务入门 一 您好,我是今夜写代码,今天学习下分布式事务相关理论,以及常见的解决方案,为后续掌握Seata分布式事务框奠定基础。 为什么需要分布式事务? 分布式事务主要由于存储资源的分布性,通常涉及多个数据库。 分布式…

Goland:专为Go语言设计的高效IDE

本文还有配套的精品资源,点击获取 简介:Goland是JetBrains公司开发的集成开发环境(IDE),专为Go语言设计,提供了高效的代码编辑、强大的调试工具和丰富的项目管理功能。其智能代码补全、强大的调试与测试支…

uniapp 前端解决精度丢失的问题 (后端返回分布式id)

原因: 后端使用分布式id, id为19位数,导致精度丢失 ,前端解决方法 这个是通过浏览器请求回来的数据,这个时候id 数据已经丢失了,在数据库查询不到,在调获详情接口的时候会有问题 实际的: 解决…

读书笔记-《乡下人的悲歌》

前段时间看了一些 J.D. Vance 的采访视频,几乎都是记者带着刁难的问题先手进攻,而 Vance 面带微笑,提及对方的名字,条理清晰地从对方的攻击中切回主题形成后手反制,实在让人看得过瘾。 更不可思议的是,Van…

Datawhale-AI冬令营二期

目录 一、番茄时钟(1)输入Prompt(2)创建 HTML 文件解析1:HTML结构解析2:计时器内容解析3:按钮区域解析4:脚本引用 (3)使用JavaScript实现时钟功能解析1&#…

【Sentinel】流控效果与热点参数限流

目录 1.流控效果 1.1.warm up 2.2.排队等待 1.3.总结 2.热点参数限流 2.1.全局参数限流 2.2.热点参数限流 2.3.案例 1.流控效果 在流控的高级选项中,还有一个流控效果选项: 流控效果是指请求达到流控阈值时应该采取的措施,包括三种&…

我的Qt作品(20)使用Qt+OpenCV写一个旋转/抠图/mask生成工具

使用QtOpenCV写一个旋转/抠图/mask生成工具 1、旋转功能 void FormRotate::rotateImage(const cv::Mat &src, cv::Mat &dst, double degree) //旋转 {if (fabs(degree) < 0.001){dst src;return;}//center旋转的中心点坐标//degree旋转的角度,不是弧度,>0逆时针…

win11中win加方向键失效的原因

1、可能是你把win键锁了&#xff1a; 解决办法&#xff1a;先按Fn键&#xff0c;再按win键 2、可能是可能是 贴靠窗口设置 中将贴靠窗口关闭了&#xff0c;只需要将其打开就好了

MetaRename for Mac,适用于 Mac 的文件批量重命名工具

在处理大量文件时&#xff0c;为每个文件手动重命名既耗时又容易出错。对于摄影师、设计师、开发人员等需要频繁处理和整理文件的专业人士来说&#xff0c;找到一款能够简化这一过程的工具是至关重要的。MetaRename for Mac 就是这样一款旨在提高工作效率的应用程序&#xff0c…

JavaScript甘特图 dhtmlx-gantt

背景 需求是在后台中&#xff0c;需要用甘特图去展示管理任务相关视图&#xff0c;并且不用依赖vue&#xff0c;兼容JavaScript原生开发。最终使用dhtmlx-gantt&#xff0c;一个半开源的库&#xff0c;基础功能免费&#xff0c;更多功能付费。 甘特图需求如图&#xff1a; 调…

VSCode下载安装指南

VSCode下载 通过网盘分享的文件&#xff1a;VSCodeUserSetup-x64-1.96.2.exe 链接: https://pan.baidu.com/s/1l7fdxeALnyeuUe1a5l0aqQ?pwdb8y3 提取码: b8y3 –来自百度网盘超级会员v6的分享 VSCode安装 1、下载好之后双击下图 2、我同意&#xff0c;下一步 3、可以点浏…

【黑马头条】day20—xxl-job

目录 1 今日内容 1.1 需求分析 1.2 实现思路 1.3 定时计算 1.4 定时任务框架-xxljob 1.5 学习目录 2.分布式任务调度 2.1 什么是分布式任务调度 2.2 xxl-Job简介 2.3 XXL-Job-环境搭建 2.4 配置部署调度中心-docker安装 2.5 xxl-job入门案例编写 2.6 任务详解-执行…

人工智能基础软件-Jupyter Notebook

简介&#xff1a; Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。 Jupyter Notebook是以网页的形式打开&#xff0c;可以在网页页面中直接编写代码和运行代码&#xff0c;代码的运行结果也会直…

Unity功能模块一对话系统(4)实现个性文本标签

本期我们将了解如何在TMPro中自定义我们的标签样式&#xff0c;并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签&#xff0c;实现标签处延迟打印功能 2.定义<r" "></r>格式的标签&#xff0c;实现标签区间内文本片段的注释显示功能…

微信流量主挑战:三天25用户!功能未完善?(新纪元4)

&#x1f389;【小程序上线第三天&#xff01;突破25用户大关&#xff01;】&#x1f389; 嘿&#xff0c;大家好&#xff01;今天是我们小程序上线的第三天&#xff0c;我们的用户量已经突破了25个&#xff01;昨天还是16个&#xff0c;今天一觉醒来竟然有25个&#xff01;这涨…