ElasticSearch中更新数组字段中值

背景:

       我们对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脚本还可以给我们解决更多问题,后续再继续跟踪记录。

 

posted on 2020-12-31 13:22  翔游九天  阅读(4028)  评论(0编辑  收藏  举报