【发布时间】:2020-06-18 14:27:06
【问题描述】:
在 Elasticsearch 中,我有一个包含对象数组的对象。数组中的每个对象都有type、id、updateTime、value 字段。
我的输入参数是一个数组,其中包含相同类型但值和更新时间不同的对象。我想在它们存在时用新值更新对象,并在它们不存在时创建新值。
我想使用 Painless 脚本来更新它们,但要保持它们不同,因为其中一些可能重叠。问题是我需要同时使用type 和id 来保持它们的唯一性。到目前为止,我已经使用蛮力方法完成了它,嵌套了 for 循环并比较了两个数组的元素,但我对此不太满意。
其中一个想法是从源中获取数组,构建临时 HashMap 以进行快速查找,处理输入,然后将所有对象存储回源中。
我可以使用自定义对象(具有type 和id 的类)作为键创建 HashMap 吗?如果是这样,该怎么做?我无法将类定义添加到脚本中。
这是映射。所有字段都“禁用”,因为我仅将它们用作中间状态并使用其他字段进行查询。
{
"properties": {
"arrayOfObjects": {
"properties": {
"typ": {
"enabled": false
},
"id": {
"enabled": false
},
"value": {
"enabled": false
},
"updated": {
"enabled": false
}
}
}
}
}
示例文档。
{
"arrayOfObjects": [
{
"typ": "a",
"id": "1",
"updated": "2020-01-02T10:10:10Z",
"value": "yes"
},
{
"typ": "a",
"id": "2",
"updated": "2020-01-02T11:11:11Z",
"value": "no"
},
{
"typ": "b",
"id": "1",
"updated": "2020-01-02T11:11:11Z"
}
]
}
最后是当前形式的脚本的一部分。脚本还做了一些其他的事情,所以为了简洁起见,我把它们删掉了。
if (ctx._source.arrayOfObjects == null) {
ctx._source.arrayOfObjects = new ArrayList();
}
for (obj in params.inputObjects) {
def found = false;
for (existingObj in ctx._source.arrayOfObjects) {
if (obj.typ == existingObj.typ && obj.id == existingObj.id && isAfter(obj.updated, existingObj.updated)) {
existingObj.updated = obj.updated;
existingObj.value = obj.value;
found = true;
break;
}
}
if (!found) {
ctx._source.arrayOfObjects.add([
"typ": obj.typ,
"id": obj.id,
"value": params.inputValue,
"updated": obj.updated
]);
}
}
【问题讨论】:
-
你的脚本现在是什么样子的?你也可以分享一些文档吗?映射的相关部分也会很好。
-
@joe 完成。希望这就足够了。如果需要,我很乐意添加更多内容。
-
谢谢,有帮助。
标签: elasticsearch hashmap elasticsearch-painless