追加更新,學名不知道叫啥,我這里指在歷史數據的基礎上,追加數據更新。比如 價格數據,我在價格字段里面保存了一個每天價格的數組,追加更新的時候在數組的后面直接add,而不是像一般情況那樣覆蓋。
ES追加更新采用painless腳本來實現。
1. 准備
第一步, 新建索引,創建mapping
### 創建 v0_test 的 map PUT {{host}}/{{index}}/_mapping content-type: application/json { "properties": { "nid": { "type": "keyword" }, "price": { "type": "text" }, "quantity":{ "type":"integer" }, "tags" : { "type": "keyword" } } }
nid 是作為id查詢詳情使用;
price 字段這里設為text類型,用於測試 字符串 追加;
quantity 字段設為integer,用於測試 整型數組 追加;
tags 設為keyword, 用於測試 字符串數組 追加。
第二步,創建測試數據
測試數據1:
### 創建一條數據 POST {{host}}/{{index}}/_doc content-type: application/json { "nid":"9", "price":"10.0,11.0,13.2", "quantity":[9,13], "tags" : ["red", "blue"] }
數據1各個字段都已經初始化。
看一下入庫結果:
測試數據2:
### 創建一條數據 POST {{host}}/{{index}}/_doc content-type: application/json { "nid":"10", "price":"10.0,11.0,13.2" }
測試數據2數組quantity 和 tags 沒有初始化。
入庫結果:
2. 文本追加更新
這里用測試數據2做文本追加更新實驗:
### 文本 追加更新 POST {{host}}/{{index}}/_update_by_query content-type: application/json { "query": { "term":{ "nid":"10" } }, "script": { "lang": "painless", "inline": "ctx._source.price = ctx._source.price + params.newprice", "params": { "newprice": ",15.0" } } }
這里再price后追加了一個字符串 “,15.0”
追加結果:
可以看到price后面已經成功追加了
3. 數組追加更新
數組追加更新先嘗試已經初始化的數組,用測試數據1
### 數組 追加更新 POST {{host}}/{{index}}/_update_by_query content-type: application/json { "query": { "term":{ "nid":"9" } }, "script": { "lang": "painless", "inline": "ctx._source.quantity.add(params.newparam)", "params": { "newparam": 43 } } }
在quantity字段的后面追加 一個 43
追加結果:
然后我們用測試數據2試試追加更新數組,測試數據2的數組字段是沒有初始化的,測試數據2的nid是 10
結果報錯了。
修改一下腳本:
### 空數組 追加更新 POST {{host}}/{{index}}/_update_by_query content-type: application/json { "query": { "term":{ "nid":"8" } }, "script": { "lang": "painless", "inline": "if (!(ctx._source.quantity instanceof List)) {ctx._source.quantity = [params.newparam]} else ctx._source.quantity.add(params.newparam)", "params": { "newparam": 43 } } }
添加一個是否為List的判斷,再追加更新
成功更新。
然后我們同樣用這個辦法來追加更新字符串數組:
### 空字符串數組 追加更新 POST {{host}}/{{index}}/_update_by_query content-type: application/json { "query": { "term":{ "nid":"10" } }, "script": { "lang": "painless", "inline": "if (!(ctx._source.tags instanceof List)) {ctx._source.tags = [params.newparam]} else ctx._source.tags.add(params.newparam)", "params": { "newparam": "顏色" } } }
更新結果:
依舊是成功的。
painless 腳本語言教程: https://www.elastic.co/guide/en/elasticsearch/painless/7.2/painless-lang-spec.html