首页/数据/NoSQL 速查/_update_by_query 按条件批量更新
Elasticsearch89 条

_update_by_query 按条件批量更新

update_by_query 先快照查询再逐条更新,默认遇版本冲突中止;大批量操作建议设 slices 并行、wait_for_completion=false 异步执行,并用 _tasks 跟踪。

NoSQL 速查数据更新于 2026-10-13

update_by_query 做什么

update_by_query 先按查询条件做一次快照,再对命中的文档逐条执行更新脚本。它默认遇到版本冲突就中止,也可以选择跳过冲突继续。因为每条文档都要重新索引一遍,所以目标索引不能关闭 _source,否则整个操作无法执行。

基本信息

接口POST /<index>/_update_by_query
常用参数conflicts=proceed、slices=auto、refresh=true、wait_for_completion=false
前置条件文档必须保留 _source,脚本基于原始文档重新索引
返回计数updated、version_conflicts、batches、failures、noops
跟踪方式异步执行后用 _tasks 接口查看进度

典型使用场景

  • 批量修正历史脏数据:给存量文档补字段或统一默认值
  • 给老数据补上新版本才有的标记字段
  • 按条件重算派生字段,例如把统计口径换成新规则
  • 把某个布尔标记批量置为真或假
  • 用脚本移除字段,替代不支持字段级删除的写法

常用写法

常用写法
# 按条件批量更新并递增计数
POST /my-index/_update_by_query?conflicts=proceed&slices=auto
{ "query": { "term": { "flag": true } },
  "script": { "source": "ctx._source.count += params.inc", "params": { "inc": 1 } } }

# 异步执行,避免请求超时
POST /my-index/_update_by_query?wait_for_completion=false
{ "query": { "term": { "flag": true } },
  "script": { "source": "ctx._source.tag = 'v2'" } }

# 跟踪任务进度
GET /_tasks?detailed=true&actions=*byquery

# 执行前先核对命中数量,避免误改范围
GET /my-index/_count
{ "query": { "term": { "flag": true } } }

返回计数读法

计数含义异常信号
updated实际完成更新的文档数远小于预期说明查询条件写窄了
version_conflicts版本冲突次数使用跳过冲突策略时必须核对
noops脚本执行但结果没变化的文档数占比高说明脚本没起作用
failures失败明细数组非空时要逐条看原因再重跑
操作期间新写入的文档是否被处理取决于快照时刻,长任务跑完后建议再执行一轮同条件校验,确认没有遗留文档。
slices=auto 会按分片数自动切分并行任务,写放大与 CPU 占用随之上升;在写入高峰执行时把 slices 限成较小值(如 2 到 4)比直接 auto 更可控,慢一点但不会把节点打满。

易错点

  • 在持续写入的索引上做大范围更新会放大段合并压力,应放低 refresh 频率或安排到业务低峰执行
  • 使用 conflicts=proceed 会跳过冲突版本,最终更新数量与预期不符,必须核对响应里的 version_conflicts
  • 索引关闭了 _source 时该操作无法执行,应通过索引模板统一保留 _source,避免个别索引配置不一致
  • 把 update_by_query 当作实时生效的手段:它按快照逐条处理,执行期间读到的是中间状态,业务侧需要容忍这种不一致窗口

数据来源与参考

  • Elasticsearch Guide: Update By Query API
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌