Elasticsearch 提供了强大的 RESTful API 来执行这些操作,通常使用 POSTPUTDELETE HTTP 方法。


1. 更新文档 (Update)

更新文档主要有两种方式:部分更新全量替换

a) 部分更新 (_update API)

这是最常用的更新方式,允许你只修改文档中的特定字段,而不需要重新索引整个文档。它遵循“获取-修改-重新索引”的流程,但所有操作在单个 API 调用中原子性完成。

  • HTTP 方法: POST
  • 端点格式: <index_name>/_update/<document_id>

请求体: 主要使用 doc 参数来指定要更新的字段。

示例: 将 ID 为 101 的文档中的 title 字段改为 “Updated Title”,并添加一个新字段 tags

POST my_index/_update/101
{
  "doc": {
    "title": "Updated Title",
    "tags": ["search", "elasticsearch"]
  }
}

响应:

{
  "_index" : "my_index",
  "_id" : "101",
  "_version" : 2, // 版本号会增加
  "result" : "updated" // 表示更新成功
}

高级特性

  • 脚本更新: 你可以使用 Painless 脚本进行更复杂的逻辑更新。

    POST my_index/_update/101
    {
      "script" : {
        "source": "ctx._source.views += params.increment",
        "params": {
          "increment": 1
        }
      }
    }
    

    (上述脚本将 views 字段的值增加 1)

  • upsert: 如果文档不存在,则执行插入操作。

    POST my_index/_update/102
    {
      "doc": {
        "title": "A New Document"
      },
      "upsert": { // 如果 ID 102 不存在,则插入 upsert 的内容
        "title": "An Upserted Document",
        "created_at": "2023-10-25"
      }
    }
    
b) 全量替换

虽然叫“更新”,但本质上是先删除旧文档,再索引一个新文档。你需要提供完整的文档内容。

  • HTTP 方法: PUTPOST
  • 端点格式: <index_name>/_doc/<document_id>

示例

PUT my_index/_doc/101
{
  "title": "A Completely New Title",
  "content": "This is the entire new content of the document.",
  "new_field": "This field didn't exist before."
}

注意: 执行此操作后,原文档中所有未在新请求体中指定的字段都将丢失。


2. 删除文档 (Delete)

删除操作相对直接,你需要指定索引和文档的 ID。

  • HTTP 方法: DELETE
  • 端点格式: <index_name>/_doc/<document_id>

示例: 删除 ID 为 101 的文档。

DELETE my_index/_doc/101

响应:

{
  "_index" : "my_index",
  "_id" : "101",
  "_version" : 3, // 版本号依然会增加,这对于并发控制很重要
  "result" : "deleted" // 表示删除成功
}

重要注意事项

  1. 找不到文档: 如果你尝试删除一个不存在的文档,Elasticsearch 会返回 "result" : "not_found",但 HTTP 状态码仍然是 404。这不算是错误,只是表明要执行的操作无需执行。
  2. 版本控制: 删除操作也会增加文档的版本号,这是一种乐观锁机制,防止在删除过程中基于旧版本数据的并发修改。
  3. 物理删除: 删除文档后,它并不会立即从磁盘上物理清除,而是被标记为已删除。这些数据会在后续段合并(Segment Merge)时被真正清理掉。

3. 按查询条件更新或删除

你可以使用 Query DSL 来匹配符合特定条件的文档,然后对它们进行批量更新或删除。

a) 按查询更新 (_update_by_query)
  • 端点: <index_name>/_update_by_query

示例: 将所有由 John 创作的文档的 status 字段设置为 reviewed

POST my_index/_update_by_query
{
  "query": { 
    "term": { // 查询条件,匹配 author 字段为 John 的文档
      "author": "John"
    }
  },
  "script": {
    "source": "ctx._source.status = 'reviewed'"
  }
}
b) 按查询删除 (_delete_by_query)
  • 端点: <index_name>/_delete_by_query

示例: 删除所有 status 字段为 obsolete 的文档。

POST my_index/_delete_by_query
{
  "query": { 
    "term": {
      "status": "obsolete"
    }
  }
}

警告_delete_by_query 是一个威力巨大的操作,执行前务必再三确认查询条件是否正确,以免误删重要数据。建议先在测试环境验证,或使用 dry_run 参数进行试运行。


总结与最佳实践

操作 常用 API 说明
部分更新 POST <index>/_update/<id> 推荐。高效,只传输变化的字段。
全量替换 PUT <index>/_doc/<id> 低效,需要传输完整文档。易丢失字段,慎用。
根据ID删除 DELETE <index>/_doc/<id> 精确删除指定文档。
批量更新 _update_by_query 根据查询条件批量更新文档。
批量删除 _delete_by_query 高危操作。根据查询条件批量删除文档,需极其谨慎。
  • 工具: 可以使用 Kibana 的 Dev Tools 控制台来非常方便地执行上述所有 API 调用。
  • 客户端: 在实际应用中,应使用 Elasticsearch 官方提供的各种语言客户端(如 Java、Python High-Level Client)来执行这些操作,它们提供了更友好的封装和错误处理。
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐