首页/数据/NoSQL 速查/文档 update 与 upsert
Elasticsearch89 条

文档 update 与 upsert

更新接口支持部分字段更新(doc)、脚本更新(script)与 upsert 语义;doc_as_upsert 让文档不存在时按 doc 内容插入,是幂等写入的常用写法。

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

文档更新接口是什么

更新接口支持三种写法:doc 部分字段更新、script 脚本更新,以及 upsert 语义。doc_as_upsert 让文档不存在时按 doc 内容插入,是幂等写入的常用写法。底层机制是「取回 _source、修改、重新索引」,因此高并发下需要用 retry_on_conflict 缓解版本冲突,而不是靠加锁。

基本信息

部分更新{ "doc": { "views": 10 } } 只覆盖给定字段
脚本更新script 配合 painless 修改字段或数组元素
upsert文档缺失时插入 upsert 内容
doc_as_upsert把 doc 内容同时当作插入内容
重试retry_on_conflict 指定冲突重试次数
适用版本Elasticsearch 7.x / 8.x

典型使用场景

  • 统计字段递增:用脚本对计数器累加
  • 状态流转:只改状态字段而不动其他内容
  • 幂等写入:doc_as_upsert 保证不存在时插入
  • 数组元素追加或移除,用脚本处理
  • 批量修正字段值,配合 _bulk 提高吞吐
  • 与外部系统对账后回写核对标记

示例

示例
POST /my-index/_update/1
{
  "doc": { "views": 10, "updated_at": "2026-10-01" },
  "doc_as_upsert": true                            # 不存在则按 doc 插入
}

POST /my-index/_update/1
{
  "script": {
    "source": "ctx._source.views += params.n",       # 原子累加
    "params": { "n": 1 }
  },
  "retry_on_conflict": 3
}

写法对照

写法行为注意点
doc覆盖给定字段数组是整体替换而非追加
script按脚本修改默认只能改 _source 已有结构
upsert不存在时插入指定内容与 doc 可并存
doc_as_upsert复用 doc 作为插入内容常用于幂等写入
retry_on_conflict冲突时自动重试次数不宜过大
更新是取回再重建索引的过程,不是原地修改;高并发下用 retry_on_conflict 缓解版本冲突,同时要注意重试次数过高会放大压力。
doc 更新会整体替换同名字段的值,数组不会追加而是覆盖;需要追加元素必须使用脚本。
关闭 _source 的索引只能用脚本更新,且脚本无法读取原值,更新难度大幅上升,映射设计时不要轻易关闭 _source。
更新返回 result 为 noop 表示提交的 doc 与原值相同、没有实际改动;这属于正常结果,排查「更新没生效」时先看它。

易错点

  • doc 更新会替换同名字段整体值,数组不追加而是覆盖,追加要用脚本
  • 被更新文档关闭 _source 后只能用脚本更新,且脚本无法读取原值
  • 高并发不设 retry_on_conflict 会频繁返回版本冲突,应用侧需处理 409 并重试
  • 脚本里直接写死字段路径,字段结构变化后脚本会报错,参数化与校验要做在前面
  • 用 _update 做大批量修改而不走 _bulk,请求往返开销会让整体吞吐明显下降

数据来源与参考

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