📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

部分更新指定 ID 的文档,支持使用脚本或字段更新。

API #

POST /{index}/_update/{id}

API 的作用 #

该 API 用于部分更新文档,与 /_doc API(完全替换)不同,此 API 只修改指定的字段。

更新方式 #

方式描述
Doc 更新直接提供要更新的字段
Script 更新使用脚本动态更新文档

核心特性 #

特性描述
部分更新只修改指定字段,保留其他字段
Upsert文档不存在时自动创建
并发控制支持乐观并发控制
脚本支持支持使用 Painless 等脚本语言

API 的参数 #

路由参数 #

参数类型是否必填描述
{index}字符串必需索引名称
{id}字符串必需文档 ID

Query String 参数 #

参数类型是否必填默认值描述
routing字符串-路由值
timeout时间值30s操作超时时间
refresh字符串false刷新策略:truefalsewait_for
wait_for_active_shards字符串1等待活跃分片数:1all、具体数字
retry_on_conflict整数0版本冲突时的重试次数
doc_as_upsert布尔值false将 doc 内容作为 upsert 使用
if_seq_no整数-1序列号条件
if_primary_term整数-1主版本条件
_source布尔值/字符串true是否返回更新后的文档源
_source_include字符串-包含的字段模式
_source_exclude字符串-排除的字段模式

请求体参数 #

请求体必须包含以下字段之一:

使用 Doc 更新 #

{
  "doc": {
    "field1": "new value",
    "field2": 123
  }
}

使用 Script 更新 #

{
  "script": {
    "source": "ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count": 5
    }
  }
}

使用 Upsert(文档不存在时创建) #

{
  "doc": {
    "field1": "value"
  },
  "upsert": {
    "field1": "default value",
    "field2": 0
  }
}

使用 doc_as_upsert #

{
  "doc": {
    "field1": "value",
    "field2": 456
  },
  "doc_as_upsert": true
}

示例 #

Doc 更新 #

POST /my_index/_update/1
{
  "doc": {
    "user": "new_user",
    "status": "active"
  }
}

响应示例:

{
  "_index": "my_index",
  "_type": "_doc",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1,
  "get": {
    "_source": {
      "user": "new_user",
      "status": "active"
    }
  }
}

Script 更新 #

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

Upsert(文档不存在时创建) #

POST /my_index/_update/1
{
  "doc": {
    "views": 1
  },
  "upsert": {
    "views": 0,
    "created_at": "2026-02-04"
  }
}

doc_as_upsert #

POST /my_index/_update/1
{
  "doc": {
    "name": "Product",
    "price": 99.99
  },
  "doc_as_upsert": true
}

条件更新 #

POST /my_index/_update/1?if_seq_no=5&if_primary_term=1
{
  "doc": {
    "status": "updated"
  }
}

重试冲突 #

POST /my_index/_update/1?retry_on_conflict=3
{
  "script": {
    "source": "ctx._source.counter++"
  }
}

不返回文档源 #

POST /my_index/_update/1?_source=false
{
  "doc": {
    "field": "value"
  }
}

返回特定字段 #

POST /my_index/_update/1?_source_includes=name,status
{
  "doc": {
    "status": "active"
  }
}

使用路由 #

POST /my_index/_update/1?routing=user1
{
  "doc": {
    "last_login": "2026-02-04"
  }
}

多字段更新 #

POST /products/_update/1
{
  "doc": {
    "name": "Updated Product",
    "price": 149.99,
    "in_stock": true
  }
}

复杂脚本更新 #

POST /counter/_update/1
{
  "script": {
    "source": """
      if (ctx._source.containsKey('tags') == false) {
        ctx._source.tags = new ArrayList();
      }
      if (params.tags.contains(ctx._source.tags) == false) {
        ctx._source.tags.addAll(params.tags);
      }
    """,
    "lang": "painless",
    "params": {
      "tags": ["important", "featured"]
    }
  }
}

获取更新后的文档 #

POST /my_index/_update/1
{
  "doc": {
    "status": "processed"
  }
}

响应中会包含更新后的文档内容。

响应字段说明 #

字段描述
_index文档所在的索引
_type文档类型(固定为 _doc
_id文档 ID
_version文档版本号
result操作结果:updatednoopcreated
_shards分片信息
_seq_no序列号
_primary_term主版本号
get更新后的文档(如果 _source=true

操作结果 #

结果描述
updated文档已更新
noop文档内容无变化
created通过 upsert 创建了新文档

错误处理 #

文档不存在(未使用 upsert) #

{
  "error": {
    "type": "document_missing_exception",
    "reason": "document [1] missing"
  },
  "status": 404
}

版本冲突 #

{
  "error": {
    "type": "version_conflict_engine_exception",
    "reason": "[1]: version conflict"
  },
  "status": 409
}

脚本错误 #

{
  "error": {
    "type": "script_exception",
    "reason": "runtime error"
  },
  "status": 400
}

并发控制 #

使用序列号和主版本 #

POST /my_index/_update/1?if_seq_no=10&if_primary_term=1
{
  "doc": {
    "status": "updated"
  }
}

只有在文档的序列号为 10 且主版本为 1 时才会执行更新。

重试机制 #

POST /my_index/_update/1?retry_on_conflict=3
{
  "script": {
    "source": "ctx._source.counter++"
  }
}

当发生版本冲突时,会自动重试最多 3 次。

使用场景 #

场景 1:计数器更新 #

POST /counters/_update/page_views
{
  "script": {
    "source": "ctx._source.count++",
    "lang": "painless"
  },
  "upsert": {
    "count": 1
  }
}

场景 2:条件更新 #

POST /users/_update/123
{
  "doc": {
    "last_login": "2026-02-04T08:00:00"
  }
}

场景 3:数组操作 #

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

场景 4:批量字段更新 #

POST /products/_update/1
{
  "doc": {
    "name": "New Name",
    "price": 99.99,
    "category": "Electronics",
    "updated_at": "2026-02-04"
  }
}

脚本语言 #

Painless(推荐) #

{
  "script": {
    "source": "ctx._source.field = params.value",
    "lang": "painless",
    "params": {
      "value": 123
    }
  }
}

脚本上下文 #

变量描述
ctx._source文档的源数据
ctx.op操作类型:nonedelete
params传递给脚本的参数

性能考虑 #

操作性能影响
Doc 更新需要读取、修改、写回整个文档
Script 更新需要编译和执行脚本,较慢
重试冲突增加延迟
返回 _source增加响应大小

注意事项 #

  1. 不支持版本控制:更新 API 不支持 version 参数
  2. 完整文档读取:即使更新一个字段,也需要读取整个文档
  3. 脚本开销:脚本更新比 doc 更新开销更大
  4. 并发控制:使用 if_seq_noif_primary_term 而非 version
  5. 类型已弃用:有类型的更新 API 已被弃用