背景
客戶為了實現search after功能,必須有一個modify_at字段在更新doc的時候不能修改,也就是更新的時候如果請求body里包含了這個modify_at字段,就不更新;但是同時又要保證upsert功能,在沒有該文檔的時候,就新增該文檔。
梳理一下,客戶的需求就是在upsert的同時,實現部分更新。
實現方式
部分更新文檔的話就需要通過[update API] (https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html) 實現,通過指定文檔id來實現部分更新,部分更新可以通過plainless script或者指定doc字段來實現
另外,update API 可以實現upsert功能,在body中指定upsert字段來實現。
綜上,最終通過如下方式解決了客戶的需求:
- 第一次寫入,POST my_index/_update/1
通過script腳本實現部分更新,以及指定upsert功能在文檔1不存在時就插入:
{
"script": {
"source": "ctx._source.a = params.a;ctx._source.b = params.b;",
"lang": "painless",
"params": {
"a": 1,
"b": 1
}
},
"upsert": {
"a": 1,
"b": 1,
"modify_at": 1634819527790
}
}
或者通過指定doc字段實現部分更新:
{
"doc": {
"a": 1,
"b": 1
},
"upsert": {
"a": 1,
"b": 1,
"modify_at": 1634819527790
}
}
- 查看寫入結果, GET my_index/_doc/1
{
"_index": "x",
"_id": "1",
"_version": 1,
"_seq_no": 12,
"_primary_term": 1,
"found": true,
"_source": {
"a": 1,
"b": 1,
"modify_at": 1634819527790
}
}
- 后續更新,方式和第一次寫入相同,只不過傳值不同,客戶端對是要插入還是更新無感
{
"script": {
"source": "ctx._source.a = params.a;ctx._source.b = params.b;",
"lang": "painless",
"params": {
"a": 2,
"b": 2
}
},
"upsert": {
"a": 2,
"b": 2,
"modify_at": 1634819527790
}
}
或者
{
"doc": {
"a": 2,
"b": 2
},
"upsert": {
"a": 1,
"b": 1,
"modify_at": 1634819527790
}
}
- 獲取結果,GET my_index/_doc/1
{
"_index": "x",
"_id": "1",
"_version": 2,
"_seq_no": 13,
"_primary_term": 1,
"found": true,
"_source": {
"a": 2,
"b": 2,
"modify_at": 1634819527790
}
}