對文檔修改有兩種方法
- 全量替換
把所有的字段全部提交上去,進行更新
PUT /ecommerce/product/1
{
"name" : "jiaqiangban gaolujie yagao",
"desc" : "gaoxiao meibai",
"price" : 30,
"producer" : "gaolujie producer",
"tags": [ "meibai", "fangzhu" ]
}
一般對應到應用程序中,每次執行的流程基本是這樣的
- 應用程序先發起一個get請求,獲取到document,展示到前臺界面,供用戶查看和修改
- 用戶在前臺界面修改數據,發送到后臺
- 后臺代碼,會將用戶修改的數據在內存中進行執行,然后封裝好修改后的全量數據
- 然后發送PUT請求,到es中,進行全量替換
- es將老的document標記為deleted,然后重新創建一個新的document
- partial update
語法
post /index/type/id/_update
{
"doc": {
"要修改的少數幾個field即可,不需要全量的數據"
}
}
這種方法只用修改少量數據,不需要將全部的document數據發送過去
查詢、修改和寫回都發生在shard內部,一瞬間就完成,可能基本就是毫秒級別的,所以可以大大減少并發沖突情況。
partial update內部執行的過程
- es內部先獲取document
- 將傳過來的field更新到document的json中
- 將老的document標記為deleted
- 將修改后的新的document創建出來
優點:
- 所有查詢、修改和寫回操作,都發生在es中的一個shard內部,避免了所有的網絡數據傳輸開銷(減少2次網絡請求------和全量的對比),大大提升了性能
- 減少了查詢和修改中的時間間隔,可以有效減少并發沖突的情況
partial update也可能遇到沖突問題,可以添加兩個參數來控制一下:
- retry_on_conflict
當發生沖突時,可以重試去更新n次,如果到n次后,還沖突,就拋棄此次更新 - _version
當發生沖突時,嘗試更新到版本號為n時,停止
示例
post /index/type/id/_update?retry_on_conflict=5&version=6