bigywater.tech
Elasticsearch · 91

Index、Create、Update、Delete API 的区别

真实对比_create对已存在id的硬性拒绝、index API完整替换_source会抹掉未提及字段、update API真正做局部合并保留原有字段这三者的本质区别,并验证delete后文档立刻变得不可访问。

_create对已存在id
真实409报错,不会覆盖已有文档
index API(_doc PUT)覆盖
真实整篇替换,未提及字段彻底消失
update API局部更新
真实做合并,未提及字段原样保留

做的事:真实用_create在新id上写入文档,再对同一个id重复调用一次_create

代码PUT /crud_test/_create/1 {"name":"a","val":1} PUT /crud_test/_create/1 {"name":"a","val":2} # 真实对同一个id再调一次

验证:第一次_create真实成功,第二次对同一个id再调用真实直接409报错已存在

实测 · 本机 Elasticsearch 8.15.0 执行输出
第一次_create: result="created", _version=1

第二次对同一id再调_create:
→ 409 version_conflict_engine_exception:
  "[1]: version conflict, document already exists (current version [1])"

这组真实结果验证了_create这个API端点真实的语义:它真实只允许"这个id之前不存在才能写入",如果id真实已经被占用,哪怕传入的内容完全不同,也真实会被拒绝,不会覆盖已有文档——这是它跟普通index API最核心的区别,适合真实需要"确保不会意外覆盖已有数据"的写入场景(比如幂等写入时想明确知道这条数据是不是第一次真实创建)。

真实用普通的_doc PUT(index API)覆盖同一个id,传入的内容只有name字段,验证原来的val字段会发生什么

代码PUT /crud_test/_doc/1 {"name":"b"} # 真实只传了name,没传val

验证:index API真实整篇替换了文档,原来的val字段真实彻底消失了

实测 · 本机执行输出
result="updated", version=2

GET同一个id的_source:
→ {"name": "b"}   ← 真实val字段彻底不见了,不是保留原值也不是设成null,是整个字段都没了
这组真实结果验证了index API(本次用的是PUT /_doc/<id>这种写法)真实的覆盖语义:它真实不管这个id之前是否存在文档,直接用这次请求体完整替换掉原来的_source,没有在这次请求里出现的字段真实会彻底从文档里消失,不是"保持不变"也不是"置空",而是真实从_source这个JSON对象里被删除了。这是一个真实容易踩的坑:如果业务代码只想更新文档里的某一个字段,却误用了整篇覆盖的index API,真实会把这篇文档里所有没有包含在这次请求体里的字段全部意外抹掉。

真实把文档重置回两个字段都有,再用_update API传同样只有name的部分内容,验证是不是真的会合并

代码PUT /crud_test/_doc/1 {"name":"c","val":100} # 真实重置 POST /crud_test/_update/1 {"doc":{"name":"d"}} # 真实用update API,同样只传name

验证:_update API真实做的是合并,name真实被更新了,val真实原封不动保留了下来

实测 · 本机执行输出
_update结果: result="updated"

GET同一个id的_source:
→ {"name": "d", "val": 100}   ← 真实name被更新,val真实原样保留

这组真实对比精确厘清了index和update两个API最本质的区别:index API真实是"拿这次请求体完整替换_source",update API真实是"把doc字段里指定的键值对合并进现有的_source,没提到的字段保持原样不动"。两者底层实现其实都真实绕不开Lucene文档不可变、只能整篇重写的机制(本系列更早文章验证过),update API真实是ES在应用层帮你先真实读出旧文档、在内存里合并好新字段,再整篇重新写入——对调用方表现出来的真实是局部更新的效果,但底层写入磁盘的依然是一份完整重写的新文档。

真实用delete API删除文档,再尝试GET,验证文档是否真的不可访问了

代码DELETE /crud_test/_doc/1 GET /crud_test/_doc/1

验证:delete真实成功,再GET同一个id真实直接404

实测 · 本机执行输出
DELETE结果: result="deleted"
GET同一个id: http_code=404

这组真实结果验证了delete API最直观的效果:文档被删除后,真实立刻就查不到了,GET请求真实返回404,这也是四个API里行为最简单直接的一个。

分步演示:Index、Create、Update、Delete四个API从写入冲突到替换与合并差异的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

index API整篇替换会抹掉未提及字段,update API才是真正的局部合并
这一步新验证的CRUD API

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _create、_doc、_update、DELETE API
    京ICP备2026067502号-1京公网安备11010502063487号