elasticsearch的寫操做是原子性的,能夠經過以下兩種方式實現es寫操做的樂觀鎖。html
version_type
在elasticsearch6.x被移除,故該方法不適用於6.x版本,詳見www.elastic.co/guide/en/el…git
PUT /user/user_type/1
{
"name": "tom",
"age": 18,
"doc_version": 1 // 自定義的文檔版本號,用於樂觀鎖
}
複製代碼
只更新低版本的記錄github
PUT /user/user_type/1?version=2&version_type=external_gt
{
"name": "tom",
"age": 18,
"doc_version": 2
}
複製代碼
忽略版本號強制更新bash
PUT /user/user_type/1?version=3&version_type=force
{
"name": "tom",
"age": 18,
"doc_version": 3
}
複製代碼
PUT /user/user_type/1
{
"name": "tom",
"age": 18,
"doc_version": 1
}
複製代碼
只更新es中doc_version
版本低的記錄less
POST /user/user_type/1/_update
{
"script": {
"source": "if(params.doc_force == true || ctx._source.doc_version < params.doc_version){for(entry in params.entrySet()){if (entry.getKey() != 'ctx') ctx._source[entry.getKey()] = entry.getValue();}}else{ctx.op = 'none'}",
"lang": "painless",
"params": {
"name": "tom",
"age": 19,
"doc_version": 19
}
}
}
複製代碼
忽略自定義版本號doc_version
強制更新記錄elasticsearch
POST /user/user_type/1/_update
{
"script": {
"source": "if(params.doc_force == true || ctx._source.doc_version < params.doc_version){for(entry in params.entrySet()){if (entry.getKey() != 'ctx') ctx._source[entry.getKey()] = entry.getValue();}}else{ctx.op = 'none'}",
"lang": "painless",
"params": {
"name": "tom",
"age": 19,
"doc_version": 19,
"doc_force": true
}
}
}
複製代碼
注:讀取script
中的params
的值時,須要過濾掉params.ctx
,緣由是es的painless
腳本會自動向params
中添加ctx
,若是不過濾,則上述的更新語法會報以下錯誤:ide
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[0l2AYvx][127.0.0.1:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "Iterable object is self-referencing itself"
},
"status": 400
}
複製代碼