首页/数据/NoSQL 速查/单文档读写与 _create
Elasticsearch89 条

单文档读写与 _create

文档级 CRUD 通过 _doc 接口完成:PUT 指定 ID 时整体替换,POST 不指定 ID 自动生成;_create 在 ID 已存在时返回 409,适合只允许插入一次的语义。

NoSQL 速查数据更新于 2026-10-13

单文档读写是什么

文档级的增删改查通过 _doc 接口完成:PUT 指定 ID 时是整篇替换,POST 不指定 ID 时自动生成;_create 在 ID 已存在时返回 409,适合只允许插入一次的语义。GET 按 ID 取文档,读取会带 _source。删除是标记删除,段合并之后空间才真正回收。部分更新要用 _update,不能靠 PUT 覆盖。

基本信息

写入PUT /<index>/_doc/<id> 指定 ID;POST /<index>/_doc 自动生成 ID
读取GET /<index>/_doc/<id>,只要原始内容可加 _source 路径
删除DELETE /<index>/_doc/<id>,段合并后才回收空间
部分更新POST /<index>/_update/<id> 配合 doc 或 script
只插入一次PUT /<index>/_create/<id>,已存在返回 409
适用版本Elasticsearch 7.x / 8.x

典型使用场景

  • 按业务主键写入或覆盖单条文档
  • 排障时按 ID 精确取回文档内容
  • 部分字段更新:只改状态或浏览量
  • 幂等写入:用固定 ID 保证重复写入不产生多份数据
  • 删除错误写入的文档
  • 验证写入结果:写后 GET 确认内容与类型

示例

示例
PUT /my-index/_doc/1
{ "title": "doc one" }                                  # 指定 ID 写入(整篇替换)

POST /my-index/_doc
{ "title": "auto id doc" }                               # 自动生成 ID

GET /my-index/_doc/1
GET /my-index/_source/1                                    # 只取原始内容

POST /my-index/_update/1
{ "doc": { "views": 10 } }                               # 部分更新

DELETE /my-index/_doc/1                                    # 删除文档

接口行为对照

接口行为使用注意
PUT _doc/<id>整篇替换(覆盖)漏字段会丢掉原值
POST _doc自动生成 ID不便于后续更新
PUT _create/<id>仅新建已存在返回 409
POST _update/<id>部分更新需先取回再重建索引
GET _doc/<id>取文档实时读取不受 refresh 影响
DELETE _doc/<id>标记删除空间延迟回收

读写实践要点

  • 覆盖写入前先 GET 原文档,避免漏字段导致数据丢失
  • 重复写入同一 ID 用 create 动作能识别冲突,便于幂等控制
  • 写入后立刻搜索看不到属于正常现象,需要 refresh 或等待刷新间隔
  • 批量场景不要逐条 PUT,改用 _bulk 降低往返开销
  • 并发更新同一文档用 _update 配合 retry_on_conflict
  • 删除大量文档优先按条件批量删除,而不是逐条 DELETE
PUT 同 ID 是覆盖写入(整篇替换),只想改部分字段请用 POST _update,否则未写到的字段会消失。
GET 按 ID 读取是实时的,不受 refresh 影响;但 _search 在 refresh 之前看不到刚写入的文档,两种接口的可见性语义不同。
删除只是标记,被删文档在段合并前仍占空间并计入 docs.deleted;大批删除后评估 force merge 的时机,避免高峰执行。
批量与并发场景优先用 _bulk 与 _update,单条 PUT 的写入吞吐低,且部分更新在并发下容易出现覆盖丢更新。

写入方式选择

  • 按业务主键覆盖写入用 PUT _doc,注意它是整篇替换
  • 只允许插入一次用 _create,重复 ID 返回 409
  • 部分字段更新用 _update 的 doc 形式
  • 数组追加或脚本计算用 _update 的 script 形式
  • 大量文档用 _bulk 提交,避免逐条往返
  • 并发更新用 _update 配合 retry_on_conflict

读取与排错

  • 按 ID 取回文档用 GET _doc,必要时只取 _source 部分路径
  • 确认写入是否生效:写后 GET 一次并核对字段类型
  • 搜索看不到刚写入的数据属于刷新延迟,不是数据丢失
  • 返回 found 为 false 说明文档不存在或已被删除
  • 批量取文档用 _mget 减少请求次数
  • 核对字段值类型优先看 _source,避免被索引形态误导
同一 ID 的写入会递增版本号,乐观并发控制依赖它;需要按版本更新时用 if_seq_no 配合 if_primary_term,冲突会返回 409。
读取时可用 _source_includes 与 _source_excludes 只取需要的字段,大文档场景能明显减少传输量;但字段过滤发生在取回之后,不会减少磁盘读取。

写入后立即可见

  • 需要立刻能搜到就显式 refresh,或用 refresh=wait_for 等待刷新
  • 批量提交用 _bulk,而不是循环单条 PUT
  • 删除大量文档后评估段合并时机,避开业务高峰
  • 按 ID 取多条文档用 _mget,减少请求往返次数

易错点

  • 用 PUT 覆盖时漏字段会丢掉原字段值,部分更新必须用 _update
  • GET 实时读取不受 refresh 影响,但 _search 在 refresh 前看不到刚写入的文档
  • 把 _create 当普通写入用,重复 ID 会返回 409,错误处理没写就会中断流程
  • 逐条 PUT 写入大量文档吞吐很低,应改成 _bulk 批量提交
  • 并发更新同一文档时不做冲突重试,后写的内容会覆盖先写的,导致更新丢失

数据来源与参考

  • Elasticsearch Guide: Index API
  • Elasticsearch Guide: Get API
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌