--- title: "更新文档" date: 2026-01-25 lastmod: 2026-01-25 description: "部分更新文档,支持脚本和字段更新" tags: ["文档操作", "更新操作", "数据修改"] summary: "部分更新指定 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 刷新策略:true、false、wait_for wait_for_active_shards 字符串 否 1 等待活跃分片数:1、all、具体数字 retry_on_conflict 整数 否 0 版本冲突时的重试次数 doc_as_upsert 布尔值 否 false 将 doc 内容作为 upsert 使用 if_seq_no 整数 否 -1 序列号条件 if_primary_term 整数 否 -1 主版本条件 _source 布尔值/字符串 否 true 是否返回更新后的文档源 _source_include 字符串 否 - 包含的字段模式 _source_exclude 字符串 否 - 排除的字段模式 请求体参数 # 请求体必须包含以下字段之一:" --- 部分更新指定 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 | 刷新策略:`true`、`false`、`wait_for` | | `wait_for_active_shards` | 字符串 | 否 | 1 | 等待活跃分片数:`1`、`all`、具体数字 | | `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 更新 ```json { "doc": { "field1": "new value", "field2": 123 } } ``` #### 使用 Script 更新 ```json { "script": { "source": "ctx._source.counter += params.count", "lang": "painless", "params": { "count": 5 } } } ``` #### 使用 Upsert(文档不存在时创建) ```json { "doc": { "field1": "value" }, "upsert": { "field1": "default value", "field2": 0 } } ``` #### 使用 doc_as_upsert ```json { "doc": { "field1": "value", "field2": 456 }, "doc_as_upsert": true } ``` ## 示例 ### Doc 更新 ```bash POST /my_index/_update/1 { "doc": { "user": "new_user", "status": "active" } } ``` **响应示例:** ```json { "_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 更新 ```bash POST /my_index/_update/1 { "script": { "source": "ctx._source.counter += params.count", "lang": "painless", "params": { "count": 5 } } } ``` ### Upsert(文档不存在时创建) ```bash POST /my_index/_update/1 { "doc": { "views": 1 }, "upsert": { "views": 0, "created_at": "2026-02-04" } } ``` ### doc_as_upsert ```bash POST /my_index/_update/1 { "doc": { "name": "Product", "price": 99.99 }, "doc_as_upsert": true } ``` ### 条件更新 ```bash POST /my_index/_update/1?if_seq_no=5&if_primary_term=1 { "doc": { "status": "updated" } } ``` ### 重试冲突 ```bash POST /my_index/_update/1?retry_on_conflict=3 { "script": { "source": "ctx._source.counter++" } } ``` ### 不返回文档源 ```bash POST /my_index/_update/1?_source=false { "doc": { "field": "value" } } ``` ### 返回特定字段 ```bash POST /my_index/_update/1?_source_includes=name,status { "doc": { "status": "active" } } ``` ### 使用路由 ```bash POST /my_index/_update/1?routing=user1 { "doc": { "last_login": "2026-02-04" } } ``` ### 多字段更新 ```bash POST /products/_update/1 { "doc": { "name": "Updated Product", "price": 149.99, "in_stock": true } } ``` ### 复杂脚本更新 ```bash 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"] } } } ``` ### 获取更新后的文档 ```bash POST /my_index/_update/1 { "doc": { "status": "processed" } } ``` 响应中会包含更新后的文档内容。 ## 响应字段说明 | 字段 | 描述 | |------|------| | `_index` | 文档所在的索引 | | `_type` | 文档类型(固定为 `_doc`) | | `_id` | 文档 ID | | `_version` | 文档版本号 | | `result` | 操作结果:`updated`、`noop`、`created` | | `_shards` | 分片信息 | | `_seq_no` | 序列号 | | `_primary_term` | 主版本号 | | `get` | 更新后的文档(如果 `_source=true`) | ## 操作结果 | 结果 | 描述 | |------|------| | `updated` | 文档已更新 | | `noop` | 文档内容无变化 | | `created` | 通过 upsert 创建了新文档 | ## 错误处理 ### 文档不存在(未使用 upsert) ```json { "error": { "type": "document_missing_exception", "reason": "document [1] missing" }, "status": 404 } ``` ### 版本冲突 ```json { "error": { "type": "version_conflict_engine_exception", "reason": "[1]: version conflict" }, "status": 409 } ``` ### 脚本错误 ```json { "error": { "type": "script_exception", "reason": "runtime error" }, "status": 400 } ``` ## 并发控制 ### 使用序列号和主版本 ```bash POST /my_index/_update/1?if_seq_no=10&if_primary_term=1 { "doc": { "status": "updated" } } ``` 只有在文档的序列号为 10 且主版本为 1 时才会执行更新。 ### 重试机制 ```bash POST /my_index/_update/1?retry_on_conflict=3 { "script": { "source": "ctx._source.counter++" } } ``` 当发生版本冲突时,会自动重试最多 3 次。 ## 使用场景 ### 场景 1:计数器更新 ```bash POST /counters/_update/page_views { "script": { "source": "ctx._source.count++", "lang": "painless" }, "upsert": { "count": 1 } } ``` ### 场景 2:条件更新 ```bash POST /users/_update/123 { "doc": { "last_login": "2026-02-04T08:00:00" } } ``` ### 场景 3:数组操作 ```bash POST /articles/_update/1 { "script": { "source": "ctx._source.tags.add(params.tag)", "lang": "painless", "params": { "tag": "featured" } } } ``` ### 场景 4:批量字段更新 ```bash POST /products/_update/1 { "doc": { "name": "New Name", "price": 99.99, "category": "Electronics", "updated_at": "2026-02-04" } } ``` ## 脚本语言 ### Painless(推荐) ```json { "script": { "source": "ctx._source.field = params.value", "lang": "painless", "params": { "value": 123 } } } ``` ### 脚本上下文 | 变量 | 描述 | |------|------| | `ctx._source` | 文档的源数据 | | `ctx.op` | 操作类型:`none`、`delete` | | `params` | 传递给脚本的参数 | ## 性能考虑 | 操作 | 性能影响 | |------|----------| | Doc 更新 | 需要读取、修改、写回整个文档 | | Script 更新 | 需要编译和执行脚本,较慢 | | 重试冲突 | 增加延迟 | | 返回 _source | 增加响应大小 | ## 注意事项 1. **不支持版本控制**:更新 API 不支持 `version` 参数 2. **完整文档读取**:即使更新一个字段,也需要读取整个文档 3. **脚本开销**:脚本更新比 doc 更新开销更大 4. **并发控制**:使用 `if_seq_no` 和 `if_primary_term` 而非 `version` 5. **类型已弃用**:有类型的更新 API 已被弃用