Elasticsearch文档操作

1. 前言

Elasticsearch索引是一组相关文档的集合,文档在Elasticsearch中用JSON来表示,每个文档都有一个唯一的”_id“字段来标识。每个文档又是一组字段的集合,字段可以有自己的数据类型,可以是数字、字符串、日期、布尔类型等,Elasticsearch可以索引文档,并对索引的文档做检索和数据分析。

2. 新增文档

我们已经知道,每个文档都有一个唯一的”_id“字段标识。新增文档时,我们既可以指定ID,也可以不指定ID,不指定ID时Elasticsearch会自动生成基于Base64编码长度为20的GUID字符串。

下面是指定ID索引文档的请求:

PUT items/_doc/1
{"title":"苹果","price":5
}

下面是不指定ID索引文档的请求:

POST items/_doc
{"title":"香蕉","price":3
}

可以看到,系统自动生成的ID值为”h1e65Y4BXAgLe9UU1-xS“

{"_index": "items","_id": "h1e65Y4BXAgLe9UU1-xS","_score": 1,"_source": {"title": "香蕉","price": 3}
}

你也许会好奇,items索引压根就不存在,为什么文档可以索引成功呢?这是因为Elasticsearch默认会自动创建索引,可以配置action.auto_create_index 来关闭,如下所示:

PUT _cluster/settings
{"persistent": {"action.auto_create_index":false}
}

再次发起一个索引不存在的文档索引请求,会得到一个异常

{"error": {"root_cause": [{"type": "index_not_found_exception","reason": "no such index [items-1] and [action.auto_create_index] is [false]","index_uuid": "_na_","index": "items-1"}],"type": "index_not_found_exception","reason": "no such index [items-1] and [action.auto_create_index] is [false]","index_uuid": "_na_","index": "items-1"},"status": 404
}

Elasticsearch默认会自动创建不存在的索引,并根据索引的文档数据动态映射字段类型,在这个例子中,price被映射为long类型,title被映射为text和keyword多数据类型。

GET items/_mapping{"items": {"mappings": {"properties": {"price": {"type": "long"},"title": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}}}}
}

除了单文档的添加,Elasticsearch还支持批量添加文档,对应的API是 _bulk,对于大量文档的写入,批量操作可以显著提升性能。如下示例,批量写入两个文档:

POST items/_bulk
{"index":{"_id":"1"}}
{"title":"苹果", "price":5}
{"index":{"_id":"2"}}
{"title":"香蕉", "price":3}

文档与文档之间必须通过换行符来分割,除了索引请求,还可以批量处理删除、更新请求,如下请求,它在items索引下添加了两篇文档、删除了一篇文档、同时更新了orders索引下的一篇文档。

POST _bulk
{"index":{"_index":"items","_id":"1"}}
{"title":"苹果", "price":5}
{"create":{"_index":"items","_id":"2"}}
{"title":"香蕉", "price":3}
{"update":{"_index":"orders","_id":"1"}}
{"doc":{"order_amount":600}}
{"delete":{"_index":"items","_id":"3"}}

关于create和index的区别是:对于相同的文档,create请求会失败,而index总是会成功,已存在的文档index请求会更新文档。

3. 更新文档

更新文档操作分为:部分更新和全量更新,部分更新即更新文档的部分字段,全量更新则是直接替换整个文档。

部分更新操作,如下示例,把1号文档的title改为”新鲜苹果“,price字段仍然会保留

POST items/_update/1
{"doc": {"title":"新鲜苹果"}
}GET items/_doc/1{"_index": "items","_id": "1","_version": 2,"_seq_no": 2,"_primary_term": 1,"found": true,"_source": {"title": "新鲜苹果","price": 5}
}

全量更新操作会直接覆盖原有文档,本质上是通过index API来完成的,如下示例,price字段会丢失:

PUT items/_doc/1
{"title":"红富士苹果"
}GET items/_doc/1{"_index": "items","_id": "1","_version": 3,"_seq_no": 3,"_primary_term": 1,"found": true,"_source": {"title": "红富士苹果"}
}

除此之外,Elasticsearch还支持upsert操作,它类似于关系数据库中的insertOrUpdate,如果文档存在则执行更新操作,不存在则执行写入操作。

如下示例,如果不存在ID=1的文档,则写入upsert部分内容,如果存在ID=1的文档,则更新doc部分的内容。

POST items/_update/1
{"doc": {"place_of_production": "山东烟台"},"upsert": {"title": "苹果","price": 5}
}

第一次请求时没有place_of_production字段,第二次请求时,因为文档已经存在,则会写入place_of_production。

除了根据指定ID更新单个文档,Elasticsearch同样支持根据搜索条件批量更新文档,对应的API是_update_by_query。批量更新文档首先需要提供“query”部分设定要更新文档的匹配条件,再提供"script"部分即文档更新的脚本。

如下示例,“match_all”匹配所有文档,将所有商品的价格上调1元钱

POST items/_update_by_query
{"query": {"match_all": {}},"script": {"lang": "painless","source": "ctx._source.price+=1"}
}

文档更新结果:

[{"_index": "items","_id": "1","_score": 1,"_source": {"price": 6,"title": "苹果"}},{"_index": "items","_id": "2","_score": 1,"_source": {"price": 4,"title": "香蕉"}}
]

4. 删除文档

删除文档同样分为根据ID单个删除和批量删除文档。需要说明的是,执行删除操作后,Elasticsearch并不会立即将文档从磁盘中物理删除掉,这是因为Elasticsearch采用段的设计来存储文档,每个段都是独立且不可变的索引结构,这么做可以提高查询性能,删除操作仅仅是将文档标记为“已删除”,在后续“段合并”阶段Elasticsearch才会真正将这些被标记为已删除的文档真正的删除并释放存储空间。

如下示例,删除items索引下的1号文档:

DELETE items/_doc/1

返回结果中,result=deleted代表删除成功,同时_version会自增1。

{"_index": "items","_id": "1","_version": 2,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1
}

还可以根据条件来批量删除文档,对应的API是_delete_by_query,如下示例,将价格大于等于4元的商品全部删除:

POST items/_delete_by_query
{"query": {"range": {"price": {"gte": 4}}}
}

返回结果中,deleted=2代表删除了两篇符合要求的文档

{"took": 37,"timed_out": false,"total": 2,"deleted": 2,"batches": 1,"version_conflicts": 0,"noops": 0,"retries": {"bulk": 0,"search": 0},"throttled_millis": 0,"requests_per_second": -1,"throttled_until_millis": 0,"failures": []
}

5. 迁移文档

除了常规的增删改查,Elasticsearch还支持将一个索引的文档迁移到另一个索引中,可以是集群内迁移,也支持跨集群迁移。

对应的API是_reindex,什么时候需要用到reindex呢?索引的一部分配置是静态的,一旦创建好就不允许更改了,比如:主分片的数量,字段的数据类型等,要更改这些静态配置就需要reindex重新构建索引。

举个例子,现在有一个news索引存储新闻数据,包含新闻的标题和评论:

POST news/_doc
{"title": "女子在小区车库遇1米多高阿富汗猎犬","comments": [{"user":"张三","content":"遛狗不拴绳,等于狗遛人"},{"user":"李四","content":"那最后是什么处理结果呢"},{"user":"王五","content":"大型犬太危险了"}]
}

默认情况下,Elasticsearch会把comments字段动态映射为Object类型,comments数组会被构建成一个扁平的键值对数组,从而丢失了单个对象之间的关系,如下所示:

{"comments.user":["张三","李四","王五"],"comments.content":["遛狗不拴绳,等于狗遛人","那最后是什么处理结果呢","大型犬太危险了"]
}

现在我们要搜索:张三评论了包含“危险”词语的新闻,搜索条件如下所示:

GET news/_search
{"query": {"bool": {"must": [{"match": {"comments.user": "张三"}},{"match": {"comments.content": "危险"}}]}}
}

因为Object类型的关系,文档竟然被意外的返回了,这明显与我们的需求不符,这个时候就需要把comments字段更改为nested数据类型,让comments数组的每个对象都单独存储。这种操作不能在news索引上直接操作,所以我们需要创建一个新的索引,然后通过reindex操作来做数据迁移。

新索引news-nested创建命令如下所示,comments类型改为nested,同时新增一个comments_count字段记录评论数:

PUT news-nested
{"mappings": {"properties": {"title":{"type": "text"},"comments":{"type": "nested"},"comments_count":{"type": "integer"}}}
}

接着,调用reindex API完成数据迁移,指定源索引和目标索引,以及迁移过程中要执行的脚本:

POST _reindex
{"source": {"index": "news"},"dest": {"index": "news-nested"},"script": {"source": "ctx._source.comments_count = ctx._source.comments.length"}
}

查看目标索引的数据,发现文档迁移成功,且comments_count字段有了

[{"_index": "news-nested","_id": "lFcm5o4BXAgLe9UUo-wj","_score": 1,"_source": {"comments": [{"user": "张三","content": "遛狗不拴绳,等于狗遛人"},{"user": "李四","content": "那最后是什么处理结果呢"},{"user": "王五","content": "大型犬太危险了"}],"comments_count": 3,"title": "女子在小区车库遇1米多高阿富汗猎犬"}}
]

再次执行nested搜索,结果没有召回任何文档,符合需求。

GET news-nested/_search
{"profile": false,"query": {"bool": {"must": [{"nested": {"path": "comments","query": {"bool": {"must": [{"match": {"comments.user": "张三"}},{"match": {"comments.content": "危险"}}]}}}}]}}
}

6. 尾巴

Elasticsearch索引是一系列相关文档的集合,文档又是一组字段的集合,每个字段有自己的数据类型,Elasticsearch可以索引并检索和分析文档数据。文档的增删改操作即可以针对单个文档进行,也可以批量处理,当面临大量操作时,使用批量API可以大幅提升性能。最后,当需要修改索引的静态配置时,可以通过reindex API在索引间迁移数据。

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

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

相关文章

vuex的store应用

1.在pakage.json加一行 2.和main同级别加一个js文件 import Vue from vue import Vuex from vuexVue.use(Vuex)export default new Vuex.Store({state: {langFlag: new Date().getTime()},mutations: {setLangFlag(state) {state.langFlag new Date().getTime()}} })3.在mai…

NewStarCTF2024-Week2-Misc-WP

目录 1、wireshark_checkin 2、wireshark_secret 3、字里行间的秘密 4、你也玩原神吗 5、Hertas Study 6、用溯流仪见证伏特台风 7、热心助人的小明 1、wireshark_checkin 直接字符串搜 flag flag{ez_traffic_analyze_isnt_it} 2、wireshark_secret 查看原始数据 导出十…

「C/C++」C++ STL容器库 之 std::map 键值对的集合容器

✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

鸿蒙网络编程系列25-TCP回声服务器的实现

1. TCP回声服务器实现可行性 在前文鸿蒙网络编程系列2-UDP回声服务器的实现中,介绍了什么是回声服务器,并且基于UDP协议实现了一个简单的回声服务器,本节将基于TCP协议实现一个类似的回声服务器。在鸿蒙API10以后,提供了TCPSocke…

【C++】使用vscode进行 C/C++ 开发,内含c_cpp_properties.json、launch.json 和 tasks.json解释

在 Visual Studio Code (VSCode) 中进行 C/C 开发时,这三个 .json 文件(c_cpp_properties.json、launch.json 和 tasks.json)分别用于配置编译、调试和代码提示等功能。它们是 VSCode 配置环境的一部分,由 C/C 扩展生成&#xff0…

将java项目jar包打包成exe服务

1.结构展示 2.注意事项 前提: 环境准备:jdk8 和 .net支持 { 1.控制面板》程序和功能》启用和关闭windows功能》.net的勾选》2.jdk8自行百度安装环境3.其他项目必须的软件环境安装等(数据库...) }第一次准备: 1.将打包好的jar包放到premiumServices.exe…

智和信通助力某大型服饰集团建设综合监控运维

某大型服饰集团成立于90年代,是广受认可的国民生活时尚品牌,近年来随着集团公司业务规模的不断扩大,信息化作为支撑集团公司业务发展的重要技术手段,信息系统无论在规模上还是在复杂程度上均有了很大程度的增加。 项目现状 当前信…

计算机网络—vlan(虚拟局域网)

内容补充 冲突域 如果两台设备同时发送数据,他们的数据会互相干扰,那么他们就处于同一冲突域,例如集线器(总线型,所有设备共享带宽)的所有端口都处于冲突域。 广播域 如果一台设备发送数据,…

babylonjs shader学习之copy shadertoy案例

shadertoy案例: 准备 const onSceneReady (scene: Scene) > {const light new HemisphericLight(light, new Vector3(0, 1, 0), scene);light.intensity 0.7;Effect.ShadersStore[planeMatVertexShader] precision highp float;attribute vec3 position;attr…

单片机输出方波

从P1.0上输出一个方波,高电平5ms,低电平10ms. #include〈reg51。h〉 unsigned char flag; sbit outP1^0; void main() { flag0; TMOD0X02; TH06; TL06; TR01; EA1; ET0…

Redis JSON介绍和命令大全

Redis JSON介绍和命令大全 Redis JSON先说说JSON是什么再说说JSON Path先推荐两个网站JSONPath JAVA clents Redis JSON 安装内存json命令语法命令url命令解释JSON.ARRAPPENDJSON.ARRINDEXJSON.ARRINSERTJSON.ARRLENJSON.ARRPOPJSON.ARRTRIMJSON.CLEARJSON.DEBUG MEMORYJSON.DE…

centOS部署Jenkins实现项目可持续自动化部署

个人看的是尚硅谷的视频,跟着实战,但因为视频是21年的,所以很容易出现jenkins插件不适配问题。 因而个人直接用较新版的jdk和jenkins. 先切换到root用户 sudo su一、安装jdk 先查询可安装版本 yum list java*安装jdk(只复制圈…

【算法】归并排序概念及例题运用

📢博客主页:https://blog.csdn.net/2301_779549673 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📢本文由 JohnKi 原创,首发于 CSDN🙉 📢未来很长&#…

爬虫日常实战

爬取美团新闻信息,此处采用两种方法实现: 注意点:因为此处的数据都是动态数据,所以一定要考虑好向下滑动数据包会更新的情况,不然就只能读取当前页即第一页数据,方法一通过更新ajax数据包网址页数&#xf…

vscode 预览markdown 文件

1. 点击左边扩展 2. 搜索“Markdown Preview Enhanced” 3. 选第一个安装即可 4. 重启vscode 5. 打开一个markdown 文件 6. 点击右上角的预览按钮

[mysql]mysql的全部单行函数

单行函数 几乎我们认识的语言都会对一些常用的功能进行,封装,有些叫函数,有些叫方法(Java),后期我们还可以自定义函数. 现在我们就当大家是没有语言基础,我们来从头开始讲.不过大家肯定接触过,中学说的函数,yf(x)f代表的就是function的缩写,这里其y2x1fx代表的就是封装的内容…

FileLink内外网文件交换——致力企业高效安全文件共享

随着数字化转型的推进,企业之间的文件交流需求日益增加。然而,传统的文件传输方式往往无法满足速度和安全性的双重要求。FileLink作为一款专注于跨网文件交换的工具,致力于为企业提供高效、安全的文件共享解决方案。 应用场景一:项…

C++大沥2019年真题——数字圈

Hi!大家好!Im#张亿,今天来讲C大沥2019年真题——数字圈 题目描述 当我们写数字时会发现有些数字有封闭区域,有的数字没有封闭区域。 数字 0 有一个封闭区域,数字 1、2、 3 都没有封闭区域,数字 4 有一个封…

word中的内容旋转90度

在vsto、Aspose.Words 中,默认没有直接的 API 可以让表格整体旋转 90 度。然而,我们可以通过一些方式来实现类似的效果,具体思路如下: 将表格插入到一个形状(Shape)或文本框中,然后旋转该形状。…

《RECONX: RECONSTRUCT ANY SCENE FROM SPARSEVIEWS WITH VIDEO DIFFUSION MODEL》论文阅读

论文地址:https://arxiv.org/pdf/2408.16767 项目地址:GitHub - liuff19/ReconX: ReconX: Reconstruct Any Scene from Sparse Views with Video Diffusion Model ---------------------------------------------------------------------------------…