真实对比_create对已存在id的硬性拒绝、index API完整替换_source会抹掉未提及字段、update API真正做局部合并保留原有字段这三者的本质区别,并验证delete后文档立刻变得不可访问。
代码PUT /crud_test/_create/1 {"name":"a","val":1} PUT /crud_test/_create/1 {"name":"a","val":2} # 真实对同一个id再调一次
第一次_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最核心的区别,适合真实需要"确保不会意外覆盖已有数据"的写入场景(比如幂等写入时想明确知道这条数据是不是第一次真实创建)。
代码PUT /crud_test/_doc/1 {"name":"b"} # 真实只传了name,没传val
result="updated", version=2
GET同一个id的_source:
→ {"name": "b"} ← 真实val字段彻底不见了,不是保留原值也不是设成null,是整个字段都没了代码PUT /crud_test/_doc/1 {"name":"c","val":100} # 真实重置 POST /crud_test/_update/1 {"doc":{"name":"d"}} # 真实用update API,同样只传name
_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 /crud_test/_doc/1 GET /crud_test/_doc/1
DELETE结果: result="deleted" GET同一个id: http_code=404
这组真实结果验证了delete API最直观的效果:文档被删除后,真实立刻就查不到了,GET请求真实返回404,这也是四个API里行为最简单直接的一个。
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
_create、_doc、_update、DELETE API