当前位置: 首页 > news >正文

【Elasticsearch从入门到精通】第15篇:Elasticsearch删除与更新API——精确操作与脚本更新

上一篇【第14篇】Elasticsearch文档检索API——GET、MGet与字段选择
下一篇【第16篇】Elasticsearch批量操作API——Bulk、Reindex与跨集群索引


摘要

数据的删除和更新是Elasticsearch文档操作中不可或缺的环节。本文全面讲解了Elasticsearch删除与更新API的使用方法,涵盖Delete API的单文档精确删除及响应码解析、Update API的三种核心用法——基于Painless脚本的灵活更新(ctx._source操作)、部分文档字段合并更新、upsert插入或更新的条件操作以及doc_as_upsert简写模式。同时深入介绍了Delete by Query查询删除和Update by Query查询更新的批量操作,包括切片(slices)并行处理策略、Task API追踪长时间操作进度、取消任务和动态调整速率等高级特性。掌握这些内容将使你能够灵活应对各种数据变更场景。

一、Delete API单文档删除

1.1 基本用法

Delete API(DELETE)允许根据文档ID从索引中删除JSON文档:

DELETEtwitter/_doc/1

如果文档存在且被成功删除,响应如下:

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

1.2 响应码说明

状态码含义说明
200文档已找到并删除result为"deleted"
404文档不存在result为"not_found"
409版本冲突并发操作时版本不匹配

注意:即使文档不存在,Delete API也会返回_version递增。在Elasticsearch内部,旧文档只是被标记为已删除,并不会立即从磁盘中移除,后台的段合并过程会在适当时机清除这些标记数据。

1.3 带版本控制的删除

可以使用乐观并发控制来确保删除的是正确版本的文档:

DELETEtwitter/_doc/1?if_seq_no=1&if_primary_term=1

如果序列号不匹配,操作将返回版本冲突错误。

二、Update API基本用法

2.1 工作原理

Update API(_update)允许根据提供的脚本或部分文档来更新已有文档。其内部流程为:

  1. 从索引中获取文档(Get操作)
  2. 运行脚本或合并部分文档(Modify操作)
  3. 将结果重新索引(Reindex操作)

因此,Update API本质上是一次"读取-修改-写入"的操作。它使用版本控制来确保在Get和Reindex期间没有发生其他更新。

注意:此操作仍然意味着文档的完全重新索引,只是减少了一些网络往返,并降低了Get和Reindex操作之间版本冲突的可能性。需要启用_source才能使用此功能。

三、使用Painless脚本更新

3.1 Painless脚本基础

Painless是Elasticsearch默认的脚本语言,专门为Elasticsearch设计,具有高性能和安全性。在Update API中使用脚本可以实现灵活的更新逻辑。

3.2 增加计数器

以下脚本将counter字段的值增加指定数量:

POSTtwitter/_update/1{"script":{"source":"ctx._source.counter += params.count","lang":"painless","params":{"count":4}}}

3.3 向列表添加元素

tags列表字段中添加标签(如果标签已存在,仍会被添加,因为这是列表操作):

POSTtwitter/_update/1{"script":{"source":"ctx._source.tags.add(params.tag)","lang":"painless","params":{"tag":"blue"}}}

3.4 从列表删除元素

从标签列表中删除指定标签。需要先定位元素的位置再删除:

POSTtwitter/_update/1{"script":{"source":"ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag))","lang":"painless","params":{"tag":"blue"}}}

3.5 添加和删除字段

添加新字段

POSTtwitter/_update/1{"script":{"source":"ctx._source.new_field = params.value","lang":"painless","params":{"value":"hello"}}}

删除字段

POSTtwitter/_update/1{"script":{"source":"ctx._source.remove('new_field')","lang":"painless"}}

3.6 条件操作

根据条件执行不同的操作。以下示例中,如果tags字段包含green,则删除文档;否则不执行任何操作(noop):

POSTtwitter/_update/1{"script":{"source":"if (ctx._source.tags.contains('green')) { ctx.op = 'delete'; } else { ctx.op = 'noop'; }","lang":"painless"}}

3.7 脚本中可用的上下文变量

除了ctx._source外,还可以通过ctx映射访问以下变量:

变量说明
_index文档所属索引
_type文档类型
_id文档ID
_version文档版本号
_routing路由值
_now当前时间戳
_op操作类型(update/noop/delete)

四、部分字段更新(doc)

4.1 基本用法

Update API支持传递部分文档进行更新,在内部完成合并操作(简单的递归合并):

POSTtwitter/_update/1{"doc":{"name":"new_name","age":20}}

上述请求会将nameage字段与现有的_source合并,其他字段保持不变。

4.2 detect_noop避免无效更新

默认情况下,如果doc中的字段值与原文档完全相同,Elasticsearch会跳过更新,响应返回"result": "noop"

POSTtwitter/_update/1{"doc":{"name":"new_name"}}

如果name的值未变,响应为:

{"_id":"1","result":"noop"}

可以通过设置"detect_noop": false来禁用此行为,强制执行更新:

POSTtwitter/_update/1{"doc":{"name":"new_name"},"detect_noop":false}

注意:如果同时指定了docscript,则doc会被忽略。建议将部分文档字段放在脚本本身中。

五、upsert与doc_as_upsert

5.1 upsert操作

upsert元素用于处理"文档不存在则插入,存在则更新"的场景:

POSTtwitter/_update/2{"script":{"source":"ctx._source.counter += params.count","lang":"painless","params":{"count":1}},"upsert":{"counter":1}}

首次执行(文档不存在):执行创建操作,"result": "created"

再次执行(文档已存在):执行脚本更新,"result": "updated"

5.2 scripted_upsert参数

如果不管文档是否存在都希望运行脚本,可以设置scripted_upsert: true

POSTtwitter/_update/2{"scripted_upsert":true,"script":{"source":"if (ctx._source.counter == null) { ctx._source.counter = 1; } else { ctx._source.counter += 1; }","lang":"painless"},"upsert":{}}

5.3 doc_as_upsert参数

doc_as_upsert是一种简写模式,当文档不存在时使用doc的内容作为新文档插入:

POSTtwitter/_update/2{"doc":{"name":"kimchy","counter":1},"doc_as_upsert":true}

5.4 Update API三种模式对比

模式参数文档存在时文档不存在时适用场景
脚本更新script执行脚本报错复杂逻辑更新
部分更新doc合并字段报错简单字段更新
条件插入upsert执行脚本插入upsert内容计数器、状态管理
脚本插入scripted_upsert执行脚本执行脚本脚本统一处理初始化
文档插入doc_as_upsert合并字段插入doc内容简单的插入或更新

六、Delete by Query查询删除

6.1 基本用法

Delete by Query(_delete_by_query)对每个与查询匹配的文档执行删除操作:

POSTtwitter/_delete_by_query{"query":{"match":{"message":"some message"}}}

响应如下:

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

6.2 版本冲突处理

_delete_by_query在启动时获取索引快照,使用内部版本控制删除匹配内容。如果文档在快照和删除请求之间被修改,会出现版本冲突。

通过设置conflicts=proceed可以让操作在版本冲突时继续执行:

POSTtwitter/_delete_by_query?conflicts=proceed{"query":{"match_all":{}}}

6.3 多索引操作

可以同时对多个索引执行查询删除:

POSTtwitter,blog/_delete_by_query{"query":{"match_all":{}}}

6.4 关键参数说明

参数说明默认值
refresh完成后刷新所有涉及分片不刷新
scroll_size滚动批次大小1000
requests_per_second限速(-1为不限速)-1
wait_for_completion是否等待完成(false返回Task)true
timeout每个写请求的超时时间1m
scroll搜索上下文保持时间5m
slices切片数量(并行处理)1

6.5 切片并行处理

_delete_by_query支持切片滚动,使删除过程可以并行执行。

自动切片

POSTtwitter/_delete_by_query?conflicts=proceed&slices=auto{"query":{"match_all":{}}}

auto将为每个分片使用一个切片。手动切片时,建议遵循以下准则:

  • 切片数等于索引分片数时性能最佳
  • 删除性能随切片数和可用资源线性扩展
  • 切片数不要大于分片数量,否则会增加额外开销

七、Update by Query查询更新

7.1 基本用法

Update by Query(_update_by_query)对索引中的每个文档执行更新操作:

POSTtwitter/_update_by_query?conflicts=proceed

上述请求会重新索引所有文档,适用于获取新添加的映射字段。

7.2 带查询条件的更新

结合DSL查询,只更新匹配特定条件的文档:

POSTtwitter/_update_by_query{"query":{"term":{"user":"kimchy"}}}

7.3 使用脚本更新

可以在更新中使用脚本修改文档内容:

POSTtwitter/_update_by_query{"query":{"term":{"user":"kimchy"}},"script":{"source":"ctx._source.likes++","lang":"painless"}}

7.4 脚本中的ctx.op控制

_update_by_query的脚本中,可以设置ctx.op来控制对文档的操作:

ctx.op值行为
update(默认)更新文档
noop跳过该文档
delete删除该文档

7.5 获取新映射属性

_update_by_query的一个重要应用场景是获取新添加的映射属性。例如:

PUTtwitter/_mapping{"properties":{"flag":{"type":"keyword"}}}POSTtwitter/_update_by_query

这样所有文档都会被重新索引,新添加的flag字段会被提取出来。

八、Task API追踪操作进度

8.1 获取任务状态

对于长时间运行的查询删除或查询更新操作,可以使用Task API追踪进度:

GET_tasks?detailed=true&actions=*/delete/byquery

或者使用任务ID直接查询:

GET_tasks/r1A2WoRbTwKZ516z6NEs5A:36619

响应中的status字段包含任务的实际进度信息:

{"completed":false,"task":{"node":"r1A2WoRbTwKZ516z6NEs5A","id":36619,"type":"transport","action":"indices:data/write/delete/byquery","status":{"total":119,"deleted":60,"batches":1,"version_conflicts":0,"noops":0,"retries":{"bulk":0,"search":0}}}}

8.2 异步执行

设置wait_for_completion=false,让操作在后台执行,立即返回任务ID:

POSTtwitter/_delete_by_query?wait_for_completion=false{"query":{"match_all":{}}}

8.3 取消任务

使用取消任务API终止正在运行的删除/更新操作:

POST_tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel

8.4 动态调整速率

在运行时使用_rethrottleAPI动态调整操作速率:

POST_delete_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1

九、总结与最佳实践

9.1 核心要点回顾

  1. Delete API提供精确的单文档删除能力,支持乐观并发控制
  2. Update API支持三种模式:脚本更新(灵活复杂)、doc部分更新(简单直接)、upsert(条件插入)
  3. Painless脚本是更新的核心工具,通过ctx._source操作文档字段
  4. Delete/Update by Query实现批量删除和更新,支持切片并行处理
  5. Task API提供长时间操作的进度追踪、取消和速率调整能力
  6. detect_noopconflicts=proceed是优化更新性能的重要手段

9.2 生产环境最佳实践

  • 优先使用doc部分更新:简单的字段修改优先使用doc而非脚本,性能更好
  • 合理使用upsert:计数器、状态管理等场景使用upsert避免"先查后写"的竞态条件
  • 批量操作切片化:大数据量的_delete_by_query_update_by_query务必使用切片并行
  • 速率控制:在业务低峰期执行大批量删除/更新,并使用requests_per_second限制对集群的影响
  • 异步执行:大批量操作使用wait_for_completion=false异步执行,通过Task API监控进度

上一篇【第14篇】Elasticsearch文档检索API——GET、MGet与字段选择
下一篇【第16篇】Elasticsearch批量操作API——Bulk、Reindex与跨集群索引


http://www.cnnetsun.cn/news/2532112.html

相关文章:

  • Taotoken多模型路由在单一服务故障时的体验保障
  • 5分钟快速上手:在电脑上免费畅玩Switch游戏的终极指南
  • 别再只调PID了!用声学定位给你的智能小车/机器人装上‘耳朵’(开源代码分享)
  • 三分钟上手:iCloud+匿名邮箱批量生成终极指南
  • SVGnest终极指南:如何免费优化材料切割布局,减少90%浪费
  • Fast-GitHub:终极免费解决方案,让GitHub访问速度提升100倍
  • 从微服务架构师视角:用Docker+Seata+Nacos搞掂分布式事务,你的配置真的安全吗?
  • 从STM32迁移到智芯车规MCU:我的开发环境踩坑与快速配置指南
  • 飞书文档导出工具:3步实现知识库批量迁移与备份
  • 解锁高效答辩新方式,okbiye AI 赋能一键打造优质毕业汇报文稿
  • AutoUnipus:终极U校园自动化答题解决方案,五分钟实现100%正确率
  • AI工程化落地的三大瓶颈与实战破局路径
  • XB1ControllerBatteryIndicator终极指南:5分钟解决Xbox手柄电量焦虑
  • 2026论文隐藏级降AIGC网站大曝光:一键压到安全线谁最稳
  • 谷歌外链怎么发:新手必看的3种免费高权重发帖渠道
  • 别再死记硬背了!用Multisim仿真软件,5分钟搞懂三极管放大电路的静态工作点设置与失真分析
  • 缓存一致性协议与侧信道攻击:Shield Bash攻击原理与防御
  • 【限时解密】Midjourney内部颗粒渲染引擎逻辑:基于逆向API日志的噪声生成时序图(仅开放72小时,含调试token领取)
  • UE5.4.4视频不导入实战:绕过Content Browser直连文件系统
  • FDA/CE/NMPA三重监管下AI Agent医疗应用合规路径全拆解,含GDPR+《人工智能医用软件分类界定指导原则》交叉对照表
  • 【监管红线预警】:AI Agent在财务报告生成中触发审计失败的4种隐蔽模式(附证监会2024Q2处罚案例编码表)
  • TMS320F28069 CLA内存配置避坑指南:从CMD文件到消息RAM的实战解析
  • RoboMaster舵轮底盘运动控制原理详解:从VxVyVw到八个电机指令的完整数学推导与代码实现
  • 从LED到LD:用OptiSystem手把手教你搞定光通信仿真(含参数设置避坑指南)
  • 不止是操作:用CST场监视器搞定天线平台耦合仿真(含Field Source实战)
  • 从原始数据到实际物理量:手把手教你解读MPU6050的HAL库读数并校准
  • 基于springboot2+vue3的医院挂号就诊系统
  • Cadence 16.6用户必看:巧用Tcl/Tk工具导出带位号书签的智能PDF原理图(附环境变量配置)
  • Geist字体实战手册:现代数字产品的瑞士设计解决方案
  • 新手友好!CobaltStrike 4.8汉化版从安装到上线的保姆级图文教程