一、什么是partial update?
PUT /index/type/id,創建文檔&替換文檔,就是一樣的語法
一般對應到應用程序中,每次的執行流程基本是這樣的:
(1)應用程序先發起一個get請求,獲取到document,展示到前台界面,供用戶查看和修改(2)用戶在前台界面修改數據,發送到后台(3)后台代碼,會將用戶修改的數據在內存中進行執行,然后封裝好修改后的全量數據(4)然后發送PUT請求,到es中,進行全量替換(5)es將老的document標記為deleted,然后重新創建一個新的document
partial update
POST /index/type/id/_update{"doc": {"要修改的少數幾個field即可,不需要全量的數據"}}
PUT /test_index/test_type/10{"test_field1": "test1","test_field2": "test2"}
POST /test_index/test_type/10/_update{"doc": {"test_field2": "updated test2"}}
看起來,好像就比較方便了,每次就傳遞少數幾個發生修改的field即可,不需要將全量的document數據發送過去
二、partial update實現原理以及其優點
partial update直接將數據更新到document中就完成了修改,不用事先先發起一個GET請求數據進行修改然后在將修改后的數據發回去。
es內部:partial update的執行和全量替換一致。
(1)內部先get獲取document
(2)將更新的field更新到document的json中
(3)將老的document標記為deleted
(4)創建新的document
優點:
(1)所有查詢,修改和寫回操作均發生在同一個shard內,避免了不必要的網絡數據傳輸帶來的開銷,大大提升了性能(減少了兩次請求,一次GET請求,一次回寫請求)
(2)減少修改和查詢中的時間間隔,有效減少並發沖突的情況
(3)內置樂觀鎖並發控制
POST /test_index/test_type/id/_update?retry_on_conflict=2
{"doc": {"num":32}}如果更新失敗,則獲取最新的版本號再次進行更新,最多重試retry_on_conflict指定的次數
POST /test_index/test_type/11/_update?version=3
{"doc": {"num":32}}
三、基於groovy腳本的partial update
1、內置腳本
示例:
PUT /test_index/test_type/11
{"num":0,"tags":[]}
更新num字段:
POST /test_index/test_type/11/_update{"script": "ctx._source.num+=8"}
2、外部腳本
在Elasticsearch的安裝目錄下的
\config\scripts內添加指定的groovy腳本
(1)添加腳本 test_update_num.groovy
腳本
代碼:
ctx._source.num+=1
執行腳本:
POST /test_index/test_type/11/_update{"script": {"lang": "groovy","file": "test_update_num"}}
( 2)添加腳本:test-add-tags.groovy
腳本代碼:ctx._source.tags+=new_tag
執行腳本:
POST /test_index/test_type/11/_update
{"script": {"lang": "groovy","file": "test-add-tags","params": {"new_tag":"tag_value"}}}
( 3)添加腳本:test-delete-document.groovy
腳本代碼:
ctx.op=ctx._source.num==count?"delete":'none'
執行腳本:
POST /test_index/test_type/11/_update{"script": {"lang": "groovy","file": "test-delete-document","params": {"count":17}}}
(4)upsert操作
如果指定的document不存在,就執行upsert中的初始化操作;如果指定的document存在,就執行doc或者script指定的partial update操作
POST /test_index/test_type/11/_update{"script" : "ctx._source.num+=1","upsert": {"num": 0,"tags": []}
}
