背景:
我們對es中,我們會對一些數組之類的字段進行存儲,但是要更新里面數組中的某一個值,你必須得整個拉出來,在內存中處理之后再賦值修改,這樣比較消耗內存,而且隨着數據增多,這影響更大,因此特意研究了下怎么通過es去實現
解決方案:
首先想到的就是通過腳本來實現,參考了官網的文檔之后,發現可以行,es腳本文檔地址,鏈接 https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-lang-spec.html
現在kibana上實現,比如我要對tags這個字段更新,腳本如下:
POST /xx_index/_update_by_query
{
"query": {
"term": {
"_id": "111"
}
},
"script": {
"lang": "painless",
"source": "def tags= ctx._source.tags;def newTag=params.tagInfo; if (tags == null) { ctx._source.tags = [params.tagInfo];} else {tags.removeIf(item->item['tagId']==newTag['tagId']);tags.add(newTag);}",
"params": {
"tagInfo": {
"tagId": 1,
"name": "標簽",
"des": "說明",
"no": 1
}
}
}
}
通過比較tagId,先移除再新增的方式實現更新替換,因為es也支持lambda的語法,實現起來比較方便
接下來可以通過代碼來實現
public void updateTag(String id, Class clz, Tag tag) {
if(Objects.isNull(id) || Objects.isNull(encounterTag)){
return;
}
UpdateRequest updateRequest = new UpdateRequest();
String scriptStr = "def tags= ctx._source.tags;def newTag=params.tagInfo; if (tags == null) { ctx._source.tags = [params.tagInfo];} else {tags.removeIf(item->item['tagId']==newTag['tagId']);tags.add(newTag);}";
Map<String, Object> params = new HashMap<>();
params.put("tagInfo", JSONObject.toJSON(tag));
Script script = new Script( Script.DEFAULT_SCRIPT_TYPE,Script.DEFAULT_SCRIPT_LANG, scriptStr, params);
updateRequest.script(script);
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(id).withClass(clz).withUpdateRequest(updateRequest).build();
elasticsearchTemplate.update(updateQuery);
elasticsearchTemplate.refresh(clz);
}
為了更方便使用,又增加了一個可以批量增加的,實現方式類似
腳本如下:
POST /enc_encounter_list/_update_by_query
{
"query": {
"term": {
"_id": "11122"
}
},
"script": {
"lang": "painless",
"source": "def tags= ctx._source.tags;def newTag=params.tagInfo; if (tags == null) { ctx._source.tags = params.tagInfo;} else {for(def t : newTag){tags.removeIf(item->item['tagId']==t['tagId']);tags.add(t);}}",
"params": {
"tagInfo": [
{
"tagId": 1,
"name": "標簽",
"des": "說明",
"no": 1
},
{
"tagId": 2,
"name": "標簽2",
"des": "說明2",
"no": 2
}
]
}
}
}
后端類似,此處就不在贅述了。
es腳本還可以給我們解決更多問題,后續再繼續跟蹤記錄。
