追加更新,学名不知道叫啥,我这里指在历史数据的基础上,追加数据更新。比如 价格数据,我在价格字段里面保存了一个每天价格的数组,追加更新的时候在数组的后面直接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