如何使用无痛脚本执行弹性搜索 _update_by_query - 对于复杂的条件
How to perform elastic search _update_by_query using painless script - for complex condition
您能否建议如何根据条件字段更新文档(使用脚本 - 我想很轻松)?
其目的是add/or从文档中删除值
所以如果我有那些输入文档:
doc //1st
{
"Tags":["foo"],
"flag":"true"
}
doc //2nd
{
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
我想执行这样的操作:
更新所有包含 "flag=true" 的文档:
- 添加的标签:"me"、"one"
- 已删除标签:"goo"、"foo"
所以预期的结果应该是这样的:
doc //1st
{
"Tags":["me","one"],
"flag":"true"
}
doc //2nd
{
"Tags":["me","one"],
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
创建映射:
PUT documents
{
"mappings": {
"document": {
"properties": {
"tags": {
"type": "keyword",
"index": "not_analyzed"
},
"flag": {
"type": "boolean"
}
}
}
}
}
插入第一个文档:
PUT documents/document/1
{
"tags":["foo"],
"flag": true
}
插入第二个文档(请记住,对于空标签,我指定了空标签数组,因为如果您根本没有字段,则需要检查脚本是否存在字段):
PUT documents/document/2
{
"tags": [],
"flag": true
}
添加第三个文档:
PUT documents/document/3
{
"tags": ["goo"],
"flag": false
}
然后 运行 _update_by_query 它有两个数组作为参数,一个用于添加元素,一个用于删除元素:
POST documents/_update_by_query
{
"script": {
"inline": "for(int i = 0; i < params.add_tags.size(); i++) { if(!ctx._source.tags.contains(params.add_tags[i].value)) { ctx._source.tags.add(params.add_tags[i].value)}} for(int i = 0; i < params.remove_tags.size(); i++) { if(ctx._source.tags.contains(params.remove_tags[i].value)){ctx._source.tags.removeAll(Collections.singleton(params.remove_tags[i].value))}}",
"params": {
"add_tags": [
{"value": "me"},
{"value": "one"}
],
"remove_tags": [
{"value": "goo"},
{"value": "foo"}
]
}
},
"query": {
"bool": {
"must": [
{"term": {"flag": true}}
]
}
}
}
如果您随后进行以下搜索:
GET documents/_search
你会得到以下结果(我想这就是你想要的):
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [{
"_index": "documents",
"_type": "document",
"_id": "2",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "1",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "3",
"_score": 1,
"_source": {
"tags": [
"goo"
],
"flag": false
}
}
]
}
}
您能否建议如何根据条件字段更新文档(使用脚本 - 我想很轻松)?
其目的是add/or从文档中删除值
所以如果我有那些输入文档:
doc //1st
{
"Tags":["foo"],
"flag":"true"
}
doc //2nd
{
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
我想执行这样的操作:
更新所有包含 "flag=true" 的文档:
- 添加的标签:"me"、"one"
- 已删除标签:"goo"、"foo"
所以预期的结果应该是这样的:
doc //1st
{
"Tags":["me","one"],
"flag":"true"
}
doc //2nd
{
"Tags":["me","one"],
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
创建映射:
PUT documents
{
"mappings": {
"document": {
"properties": {
"tags": {
"type": "keyword",
"index": "not_analyzed"
},
"flag": {
"type": "boolean"
}
}
}
}
}
插入第一个文档:
PUT documents/document/1
{
"tags":["foo"],
"flag": true
}
插入第二个文档(请记住,对于空标签,我指定了空标签数组,因为如果您根本没有字段,则需要检查脚本是否存在字段):
PUT documents/document/2
{
"tags": [],
"flag": true
}
添加第三个文档:
PUT documents/document/3
{
"tags": ["goo"],
"flag": false
}
然后 运行 _update_by_query 它有两个数组作为参数,一个用于添加元素,一个用于删除元素:
POST documents/_update_by_query
{
"script": {
"inline": "for(int i = 0; i < params.add_tags.size(); i++) { if(!ctx._source.tags.contains(params.add_tags[i].value)) { ctx._source.tags.add(params.add_tags[i].value)}} for(int i = 0; i < params.remove_tags.size(); i++) { if(ctx._source.tags.contains(params.remove_tags[i].value)){ctx._source.tags.removeAll(Collections.singleton(params.remove_tags[i].value))}}",
"params": {
"add_tags": [
{"value": "me"},
{"value": "one"}
],
"remove_tags": [
{"value": "goo"},
{"value": "foo"}
]
}
},
"query": {
"bool": {
"must": [
{"term": {"flag": true}}
]
}
}
}
如果您随后进行以下搜索:
GET documents/_search
你会得到以下结果(我想这就是你想要的):
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [{
"_index": "documents",
"_type": "document",
"_id": "2",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "1",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "3",
"_score": 1,
"_source": {
"tags": [
"goo"
],
"flag": false
}
}
]
}
}