我创建了一个脚本,用于记录以弹性方式应用于我的文档的标记的历史记录。标签的名称是动态的,因此当我尝试将当前标签移动到历史记录字段时,对于尚未具有历史记录字段的标签,它会失败。
这是我将当前标记复制到标记历史记录字段的脚本:
script:"ctx._source.tags[params.tagName.toString()].history.add(ctx._source.tags[params.tagName.toString()].current)"
这就是文件的样子:
"tags": {
"relevant": {
"current": {
"tagDate": 1501848372292,
"taggedByUser": "dev",
"tagActive": true
},
"history": [
{
"tagDate": 1501841137822,
"taggedByUser": "admin",
"tagActive": true
},
{
"tagDate": 1501841334127,
"taggedByUser": "admin",
"tagActive": true
},
}}}}
用户可以动态添加新标签,所以我想要做的是创建历史对象(如果它不存在)然后我可以填充它。
弹性搜索脚本的文档很少,所以我希望有明智的人会知道答案,因为我确信检查字段并创建它是弹性脚本语言的基本内容。
更新
所以,重新考虑了这个索引的结构,我想要实现的目标如下:
tags:[
{hot:
{current:{tagDate:1231231233, taggedbyUser: user1, tagStatus: true},
history:[ {tagDate:123444433, taggedbyUser: user1, tagStatus: true},
{tagDate:1234412433, taggedbyUser: user1, tagStatus: true}
]
}
{interesting:
{current:{tagDate:1231231233, taggedbyUser: user1, tagStatus: true},
history:[ {tagDate:123444433, taggedbyUser: user1, tagStatus: true},
{tagDate:1234412433, taggedbyUser: user1, tagStatus: true}
]
}
]
此示例中的标记名称是" hot"并且"有趣"但是用户可以输入他们想要的任何标签名称,因此这些都不是预定义的。当用户使用弹性标记文档并且已应用的标记已经存在于弹性中时,它应该更多的是" current"标记为"历史"数组,然后覆盖"当前"标记新值。
感谢您的回复,但示例代码对我不起作用。
我认为我遇到的问题是,首先代码需要循环遍历所有标记并获取名称。然后我想将这些中的每一个与我在params中提供的名称进行比较。我认为这是第一个问题出现的地方。
然后我需要移动"当前"反对"历史"阵列。这里似乎也存在一个问题。我试图使用" ctx._source.tags [i] .history.add(params.param1),但是没有添加任何内容。
有什么想法吗?
谢谢!
答案 0 :(得分:1)
它有点复杂,因为你需要在脚本中做三件事:
history
尚不存在,请初始化数组current
标记替换为新标记假设您的初始文档如下所示(请注意没有history
):
{
"_id": "AV2uvqCUfGXyNt1PjTbb",
"tags": {
"relevant": {
"current": {
"tagDate": 1501848372292,
"taggedByUser": "dev",
"tagActive": true
}
}
}
}
为了能够执行这三个步骤,您需要运行以下脚本:
curl -X POST \
http://127.0.0.1:9200/script/test/AV2uvqCUfGXyNt1PjTbb/_update \
-d '{
"script": {
"inline": "if (ctx._source.tags.get(param2).history == null) ctx._source.tags.get(param2).history = new ArrayList(); ctx._source.tags.get(param2).history.add(ctx._source.tags.get(param2).current); ctx._source.tags.get(param2).current = param1;",
"params" : {
"param1" : {
"tagDate": 1501848372292,
"taggedByUser": "my_user",
"tagActive": true
},
"param2": "relevant"
}
}
}'
我得到了结果:
{
"_id": "AV2uvqCUfGXyNt1PjTbb",
"_source": {
"tags": {
"relevant": {
"current": {
"tagActive": true,
"tagDate": 1501848372292,
"taggedByUser": "my_user"
},
"history": [
{
"tagDate": 1501848372292,
"taggedByUser": "dev",
"tagActive": true
}
]
}
}
}
}
使用新内容parm1
(新标记)运行相同的脚本会产生:
{
"_id": "AV2uvqCUfGXyNt1PjTbb",
"_source": {
"tags": {
"relevant": {
"current": {
"tagActive": true,
"tagDate": 1501841334127,
"taggedByUser": "admin"
},
"history": [
{
"tagDate": 1501848372292,
"taggedByUser": "dev",
"tagActive": true
},
{
"tagActive": true,
"tagDate": 1501848372292,
"taggedByUser": "my_user"
}
]
}
}
}
}
如果tags
是"内部json对象"的列表,例如:
{
"tags": [
{
"relevant": {
"current": {
"tagDate": 1501841334127,
"taggedByUser": "dev",
"tagActive": true
}
}
},
{
"new_tag": {
"current": {
"tagDate": 1501848372292,
"taggedByUser": "admin",
"tagActive": true
}
}
}
]
}
你必须遍历列表才能找到正确元素的索引。我们假设您要更新元素new_tag
。首先,您需要检查此标记是否存在 - 如果存在,请获取其索引(如果不存在),从脚本返回。拥有索引,只需获得正确的元素,你就可以像以前一样。脚本如下所示:
int num = -1;
for (int i = 0; i < ctx._source.tags.size(); i++) {
if (ctx._source.tags.get(i).get(param2) != null) {
num = i;
break;
};
};
if (num == -1) {
return;
};
if (ctx._source.tags.get(num).get(param2).history == null)
ctx._source.tags.get(num).get(param2).history = new ArrayList();
ctx._source.tags.get(num).get(param2).history.add(ctx._source.tags.get(num).get(param2).current);
ctx._source.tags.get(num).get(param2).current = param1;
和wole查询:
curl -X POST \
http://127.0.0.1:9200/script/test/AV29gAnpqbJMKVv3ij7U/_update \
-d '{
"script": {
"inline": "int num = -1; for (int i = 0; i < ctx._source.tags.size(); i++) {if (ctx._source.tags.get(i).get(param2) != null) {num = i; break;};}; if (num == -1) {return;}; if (ctx._source.tags.get(num).get(param2).history == null) ctx._source.tags.get(num).get(param2).history = new ArrayList(); ctx._source.tags.get(num).get(param2).history.add(ctx._source.tags.get(num).get(param2).current); ctx._source.tags.get(num).get(param2).current = param1;",
"params" : {
"param1" : {
"tagDate": 1501848372292,
"taggedByUser": "my_user",
"tagActive": true
},
"param2": "new_tag"
}
}
}
'
结果:
{
"tags": [
{
"relevant": {
"current": {
"tagDate": 1501841334127,
"taggedByUser": "dev",
"tagActive": true
}
}
},
{
"new_tag": {
"current": {
"tagActive": true,
"tagDate": 1501848372292,
"taggedByUser": "my_user"
},
"history": [
{
"tagDate": 1501848372292,
"taggedByUser": "admin",
"tagActive": true
}
]
}
}
]
}
答案 1 :(得分:0)
我认为你可以在groovy脚本中做这样的事情
{
"script": "if( ctx._source.containsKey(\"field_name\") ){ ctx.op = \"none\"} else{ctx._source.field_name= field_value;}"
}