文章目录
1 什么是partial update
1.1 全量修改文档的原理
全量修改文档的语法: PUT index/type/1, 如果id=1的文档不存在, 则创建, 如果存在, 将发生替换原有文档的操作
PUT test/_doc/1
{
"counter" : 1, //有2个属性,counter和tags
"tags" : ["red"]
}
PUT test/_doc/1
{
"counter" : 2 //尝试覆盖
}
查询此时document结果结果:
GET test/_doc/1
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_version": 2,
"_seq_no": 1,
"_primary_term": 1,
"found": true,
"_source": {
"counter": 2 //此时只有counter属性
}
}
全量替换文档的性能比较低, 为了避免替换操作的发生, 引入partial update: 只修改指定的field, 不用全量修改数据.
1.2 修改指定field的思路
(1) 根据用户请求, 获得要修改的文档;
(2) 在内存中封装用户提交的新文档, 发送PUT请求到ES内部;
(3) 将要替换的旧文档标记为deleted;
(4) 最后将封装好的新文档存入索引中.
1.3 partial update的优势
(1) 所有的查询、修改和写回操作, 都在同一个shard中进行, 避免了网络传输的开销.
不需要: 从特定shard查询文档 -> 返回到内存 -> 内存中修改 -> 将修改的文档发送到原来的shard -> 写索引 —— 这个复杂的操作, 显著提升了性能.
(2) 减少了查询和修改的时间间隔, 可以有效减少并发冲突.
1.4 partial update的使用
我们复用官网的格式:
POST test/_doc/1/_update
{
"doc" : { //doc声明
"name" : "new_name" //需要修改的字段,该字段可以存在,也可以不存在
//如果字段已存在,则修改这个字段;如果不存在,则新增这个字段
}
}
实战:
// 添加测试数据:
PUT employee/developer/1
{
"name": "shou feng",
"sex": "male",
"age": 20
}
// partial update修改指定field:
POST employee/developer/1/_update
{
"doc": {
"age": 21
}
}
// 响应结果:
{
"_index": "employee",
"_type": "developer",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
// 查看文档, 发现age已经从20变为21了. 并且其他的字段都还存在,没有被覆盖
GET employee/developer/1
注意:url中一定是 _update 结尾的,否则即使body体加了doc,此时会把doc体当做普通的参数,导致覆盖行为
partial 与 upsert组合使用
参考 https://www.cnblogs.com/shoufeng/p/11348277.html