Skip to content

文档CRUD与版本控制

文档操作

1. 创建文档

json
# 指定ID
PUT /products/_doc/1
{
  "name": "iPhone 15",
  "price": 999,
  "category": "phone"
}

# 自动生成ID
POST /products/_doc
{
  "name": "iPhone 15",
  "price": 999
}

Response:

json
{
  "_index": "products",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {"total": 2, "successful": 1, "failed": 0}
}

2. 查询文档

json
GET /products/_doc/1

# 只返回source
GET /products/_source/1

# 批量获取
GET /products/_doc/_mget
{
  "ids": ["1", "2", "3"]
}

3. 更新文档

json
# 整体更新(覆盖)
PUT /products/_doc/1
{
  "name": "iPhone 15 Pro",
  "price": 1299
}

# 局部更新
POST /products/_doc/1/_update
{
  "doc": {
    "price": 1099
  }
}

# 脚本更新
POST /products/_doc/1/_update
{
  "script": {
    "source": "ctx._source.price += params.increment",
    "params": {"increment": 100}
  }
}

4. 删除文档

json
# 删除单个
DELETE /products/_doc/1

# 删除满足条件的
POST /products/_delete_by_query
{
  "query": {
    "term": {"category": "deprecated"}
  }
}

5. 批量操作

json
POST /products/_bulk
{"index": {"_id": "1"}}
{"name": "iPhone", "price": 999}
{"create": {"_id": "2"}}
{"name": "MacBook", "price": 1999}
{"update": {"_id": "3"}}
{"doc": {"price": 2999}}
{"delete": {"_id": "4"}}

版本控制

内部版本号

_version:每次更新递增
json
# 第一次创建
PUT /products/_doc/1
{"name": "iPhone"}

# _version = 1

# 更新
PUT /products/_doc/1
{"name": "iPhone 15"}

# _version = 2

外部版本号

json
# 使用外部系统版本
PUT /products/_doc/1?version=100&version_type=external
{"name": "iPhone 15"}

# 后续更新必须大于上一次
PUT /products/_doc/1?version=101&version_type=external
{"name": "iPhone 15 Pro"}

乐观锁

json
# 指定版本更新(版本不对则失败)
PUT /products/_doc/1?if_seq_no=1&if_primary_term=1
{"name": "iPhone 15"}

# 失败响应
{
  "error": {
    "type": "version_conflict_engine_exception",
    "reason": "[1]: version conflict"
  }
}

并发控制参数

参数说明
if_seq_no序列号
if_primary_term主分片号
version内部版本号
version_type版本类型(internal/external)

面试考点

Q: ES如何保证并发安全?

  • 乐观锁:version + seq_no + primary_term
  • 写入冲突返回409

Q: bulk失败怎么办?

  • 每条独立执行,失败不影响其他
  • 返回每条状态

Q: _source太大怎么办?

  • 禁用_source(_source: false)
  • 指定返回字段(_source: ["field1"])
  • 过滤字段(_source: {exclude: ["field1"]})

Q: _id可以修改吗?

❌ 不能,只能先删后重建

最后更新: