最近一直在研究怎么对es 数据库进行追加更新,因为无论是整个文档更新还是局部的更新,都是先找到旧的,然后标记删除,然后再添加新的文档,显然这不能满足需要对文档追加更新的需求,即不覆盖之前的记录进行更新。以下分情况进行研究:
一. 需要更新的字段为list类型
- 对list的元素进行追加更新,即增加list元素数量,list长度变化
不管是对列表还是对字符串的追加更新,都需要利用脚本来进行,script比较灵活可以自己定义你想实现的逻辑,如下,首先判断文档中有没有vuln_label这个字段(filed),没有的话添加一个这个字段,数据结构定为列表,如果有这个字段则追加更新params.tag
body = {
"script": {
"lang": "painless",
"source": "if(ctx._source.vuln_label==null){ctx._source.vuln_label=[];ctx._source.vuln_label.add(params.tag)}"
"else{ctx._source.vuln_label.add(params.tag)}",
"params": {
"tag":{
"CVE_ID": item['CVE_ID'],
"creates_time": item['created_time'],
"risk_level": item['risk_level'],
"Description": item['Description'],
"vulnerable_type": item['vulnerable_type']
}
}
}
}
- 对list元素的key:value进行追加更新,即增加list元素的键值对数量,list长度不变
思路:将需要更新的字段赋给一个空的列表对象,后根据字段的index也就是下标去遍历list种的元素,更新脚本可写为:
query = {"query": {"bool": {"must": {"exists": {"field": "vulns"}}}}}
# print(es.count(index='2021-10_cn_asset', doc_type='iot_asset', body=query))
a = es.search(index='2021-10_cn_asset', doc_type='iot_asset', scroll='5m', body=query, size=1000)
result = a['hits']['hits']
total = a['hits']['total']
scroll_id = a['_scroll_id']
for item4 in range(0, int(total / 1000) + 1):
query_scroll = es.scroll(scroll_id=scroll_id, scroll='5m')['hits']['hits']
result += query_scroll
s = []
for item in result:
ll = item['_source']['vulns']
r = range(len(ll))
for item1 in r:
if item1 == 0:
body2 = {
"script": {
"lang": "painless",
"source": "if(ctx._source.vulns!=null){ctx._source.vulns=[];ctx._source.vulns.add(params.tag)}",
"params": {
"tag": {}}}}
else:
body2 = {
"script": {
"lang": "painless",
"source": "ctx._source.vulns.add(params.tag)",
"params": {
"tag": {}}}}
以此为例,其中ll为空的列表对象,vulns为需要更新的字段,其type 为list,其中区别就是第一个元素和后面元素的更新脚本不一样。如此,即可完成列表元素种键值对的追加更新,不改变原来的结构,当然,tag中要将原来的键值对一一罗列,再加上需要增加的键值对。
二. 对字符串的追加更新
对字符串的追加更新更新和列表类似:
body={"script": {"source":"ctx._source.name+=params.tag","params":{"tag":"黄晓明"}}}
- 对字典的追加更新(这种情况建议新增一个字段),例如情况1
注意**:用source而不是inline,使用inline会有警告!**
版权声明:本文为m0_37772653原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。