elasticsearch 脚本检查字段是否存在并创建它

A D*_*Dev 5 elasticsearch

我创建了一个脚本,用于记录应用于我的弹性文档的标签的历史记录。标签的名称是动态的,因此当我尝试将当前标签移动到历史字段时,对于尚不具有历史字段的标签会失败。

这是我的脚本,用于将当前标签复制到标签历史字段:

script:"ctx._source.tags[params.tagName.toString()].history.add(ctx._source.tags[params.tagName.toString()].current)"
Run Code Online (Sandbox Code Playgroud)

这些文件是这样的:

"tags": {
                        "relevant": {
                            "current": {
                                "tagDate": 1501848372292,
                                "taggedByUser": "dev",
                                "tagActive": true
                            },
                            "history": [
                                {
                                    "tagDate": 1501841137822,
                                    "taggedByUser": "admin",
                                    "tagActive": true
                                },
                                {
                                    "tagDate": 1501841334127,
                                    "taggedByUser": "admin",
                                    "tagActive": true
                                },
                                }}}}
Run Code Online (Sandbox Code Playgroud)

用户可以动态添加新标签,所以我想要做的是创建历史对象(如果它不存在),然后我可以填充它。

可用于elasticsearch脚本的文档非常少,所以我希望明智的人能够知道答案,因为我确信检查字段并创建它是elastic脚本语言的基本内容。

更新

因此,重新考虑该索引的结构后,我想要实现的目标如下:

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}
     ]
} 
]
Run Code Online (Sandbox Code Playgroud)

此示例中的标签名称是“热门”和“有趣”,但是用户将能够输入他们想要的任何标签名称,因此这些标签名称绝不是预定义的。当用户在elastic中标记文档并且应用的标签已经存在于elastic中时,它应该将“当前”标签添加到“历史”数组中,然后用新值覆盖“当前”标签。

感谢您迄今为止的回复,但是示例代码对我不起作用。

我认为我遇到的问题是,首先代码需要循环所有标签并获取名称。然后,我想将其中每一个与我在参数中提供的名称进行比较。我认为这就是第一个问题出现的地方。

然后我需要将“当前”对象移动到“历史”数组。这里似乎也存在一个问题。我正在尝试使用“ctx._source.tags[i].history.add(params.param1),但是没有添加任何内容。

有什么想法吗?

谢谢!

Joa*_*nna 5

这有点复杂,因为您需要在脚本中做三件事:

  • 如果history尚不存在,则初始化数组
  • 将当前标签移至历史记录
  • current用新标签替换旧标签

假设您的初始文档如下所示(注意还没有history):

{
    "_id": "AV2uvqCUfGXyNt1PjTbb",
    "tags": {
        "relevant": {
            "current": {
                "tagDate": 1501848372292,
                "taggedByUser": "dev",
                "tagActive": true
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了能够执行这三个步骤,您需要运行以下脚本:

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"
        }
    }
}'
Run Code Online (Sandbox Code Playgroud)

我得到的结果是:

{
    "_id": "AV2uvqCUfGXyNt1PjTbb",
    "_source": {
        "tags": {
            "relevant": {
                "current": {
                    "tagActive": true,
                    "tagDate": 1501848372292,
                    "taggedByUser": "my_user"
                },
                "history": [
                    {
                        "tagDate": 1501848372292,
                        "taggedByUser": "dev",
                        "tagActive": true
                    }
                ]
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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"
                    }
                ]
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新 - 如果“tags”是一个列表

如果tags是“内部json对象”的列表,例如:

{
    "tags": [
        {
            "relevant": {
                "current": {
                    "tagDate": 1501841334127,
                    "taggedByUser": "dev",
                    "tagActive": true
                }
            }
        },
        {
            "new_tag": {
                "current": {
                    "tagDate": 1501848372292,
                    "taggedByUser": "admin",
                    "tagActive": true
                }
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

您必须迭代列表才能找到正确元素的索引。假设您想要更新 element 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;
Run Code Online (Sandbox Code Playgroud)

和 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"
        }
    }
}
' 
Run Code Online (Sandbox Code Playgroud)

结果:

{
    "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
                    }
                ]
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)