1.什么是partial update
PUT /index/type/id ,创建文档、更新文档操作
一般对应到应用程序中,每次的执行流程基本是这样的:
1)应用程序先发起一个get请求,获取到document,展示到前台页面上,工用户查询和修改
2)用户在前台页面上修改数据document,发送到后台
3)后台代码,会将用户修改的数据在内存中进行执行,然后封装好修改后的全量数据
4)然后发送put请求,到es中,进行全量替换
5)es将老的document标记为deleted,然后重新创建一个新的document
2.partial update原理
其实es内部对partial update的实际执行,跟全量替换方式几乎一致。
1)内部先获取document
2)将传过来的field更新到document的json中
3)将老的document标记为deleted
4)将修改后的新的document创建出来
3.partial update相对于全量替换的优点
1)所有的查询、修改和写回操作,都发生在es中的一个shard内部,避免了所有网络传输的开销(减少了2次网络请求),大大提升了性能
2)减少了查询和修改的时间间隔,可以有效减少并发冲突的情况
实际上,如果将查询放到界面上,用户修改时查询可能需要很久,10分钟、半小时,甚至于更久,然后将查询后的数据进行修改,并写回es,可能es中的数据早就被人修改了,所以并发冲突会发生很多。
4.partial update例子
普通put操作
partial update操作
5.基于groovy执行partial update操作
准备数据:
PUT /test_index/test_type/10
{
"num":0,
"tags":[]
}
1)使用内置脚本进行更新操作
POST /test_index/test_type/10/_update
{
"script": "ctx._source.num+=1"
}
执行结果
{
"_index": "test_index",
"_type": "test_type",
"_id": "10",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 6,
"_primary_term": 1
}
查询一下
GET /test_index/test_type/10
{
"_index": "test_index",
"_type": "test_type",
"_id": "10",
"_version": 2,
"found": true,
"_source": {
"num": 1,
"tags": []
}
}
2)使用外部groovy脚本进行partial update操作
在elasticsearch安装目录下的config目录中新建scripts文件夹,并在里面新建文件groovy脚本:test-add-tags.groovy
并在里面加上一行代码:
ctx._source.tags+=new_tag
在kibana中执行:
POST /test_index/test_type/10/_update
{
"script": {
"lang":"groovy", ##指定脚本语言
"file": "test-add-tags", ##指定执行的脚本
"params": {
"new_tag":"tag1" ##指定脚本中的参数的值
}
}
}
使用外部脚本进行删除操作
创建脚本test-delete-document.groovy
内容:
ctx.op=ctx._source.num==count ? 'delete':'none'
在kibana中执行
POST /test_index/test_type/10/_update
{
"script": {
"lang": "groovy",
"file": "test-delete-document",
"params": {
"count":1
}
}
}
3)upsert操作
相对于saveOrUpdate操作
例子:如果id=11的数据存在,那么就执行doc或者script的partial udpate操作,如果不存在,那么初始化一条数据
POST /test_index/test_type/11/_update
{
"script":"ctx._source.num+=1",
"upsert": {
"num":0,
"tags":[]
}
}
执行结果:
{
"_index": "test_index",
"_type": "test_type",
"_id": "11",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 3
}
再次执行时,因为已经存在,所以进行更新操作
{
"_index": "test_index",
"_type": "test_type",
"_id": "11",
"_version": 2,
"found": true,
"_source": {
"num": 1,
"tags": []
}
}