是的,Elasticsearch 中的 `PUT` 请求是覆盖式的。当你使用 `PUT` 请求向索引中写入文档时,如果文档已经存在,Elasticsearch 会完全替换整个文档的内容,而不是进行部分更新。
覆盖式的具体行为
- 文档存在时:`PUT` 请求会用新提供的 JSON 数据完全替换掉旧文档的内容。
- 文档不存在时:`PUT` 请求会创建一个新的文档,并使用提供的 JSON 数据作为文档内容。
示例
假设你有一个文档,初始内容如下:
```json
{
"name": "John Doe",
"age": 25,
"email": "john.doe@example.com"
}
```
现在,你使用 `PUT` 请求更新这个文档:
```json
PUT /users/_doc/1
{
"age": 30,
"email": "john.doe@example.com"
}
```
更新后,文档的内容将变为:
```json
{
"age": 30,
"email": "john.doe@example.com"
}
```
注意,`name` 字段在新的 `PUT` 请求中没有被包含,因此它被移除了。整个文档的内容被完全替换为新的 JSON 数据。
使用场景
- 完全替换文档:当你需要更新文档的大部分内容,或者完全重新定义文档时,`PUT` 是一个合适的选择。
- 创建新文档:当你不确定文档是否存在时,`PUT` 也可以用来创建新文档。
注意事项
- 数据丢失风险:由于 `PUT` 是覆盖式的,如果你没有在请求中包含某些字段,这些字段将被删除。因此,在使用 `PUT` 时,需要确保请求中包含了所有需要保留的字段。
- 并发问题:在多用户并发更新同一文档的场景中,`PUT` 可能会导致数据丢失或冲突。为了避免这种情况,可以使用 `if_seq_no` 和 `if_primary_term` 参数来实现乐观锁。
示例:使用乐观锁
为了避免并发冲突,可以在 `PUT` 请求中使用 `if_seq_no` 和 `if_primary_term` 参数:
```json
PUT /users/_doc/1?if_seq_no=1&if_primary_term=1
{
"age": 30,
"email": "john.doe@example.com"
}
```
如果文档的序列号(`seq_no`)或主版本号(`primary_term`)与提供的值不匹配,Elasticsearch 将拒绝此次更新操作,从而避免覆盖其他用户的更改。
总结来说,`PUT` 请求是覆盖式的,它会完全替换文档的内容。在使用时,需要谨慎处理数据,避免意外丢失字段。