【问题标题】:elasticsearch:use script to update nested field?elasticsearch:使用脚本更新嵌套字段?
【发布时间】:2016-04-14 13:55:30
【问题描述】:

我想在每次更新时将一个对象添加到nested 字段中。

例如,我有一个文档:

{
    "test":[{"remark":"remark1"}]
}

下一次,我想在测试字段中添加一个remark 对象并保存旧的remark 对象。结果是:

{
    "test":[{"remark":"remark1"},{"remark":"remark2"}]
}

如何实现?

编辑 我使用脚本:

{
    "script": "ctx._source.test= ((ctx._source.test?: []) += remarkItem)",
    "params": {
        "remarkItem": {
            "remark": "addd"
        }
    }
}

但是,我得到了例外:

{
"error": {
    "root_cause": [
        {
            "type": "remote_transport_exception",
            "reason": "[es77][10.14.84.77:9300][indices:data/write/update[s]]"
        }
    ],
    "type": "illegal_argument_exception",
    "reason": "failed to execute script",
    "caused_by": {
        "type": "script_exception",
        "reason": "Failed to compile inline script [ctx._source.test= ((ctx._source.test?: []) += remarkItem)] using lang [groovy]",
        "caused_by": {
            "type": "script_exception",
            "reason": "failed to compile groovy script",
            "caused_by": {
                "type": "multiple_compilation_errors_exception",
                "reason": "startup failed:\na8220b2cf14b8b7ebeead7f068416882d04fa25d: 1: \nclass org.codehaus.groovy.ast.expr.ElvisOperatorExpression, with its value '(ctx._source.test) ? ctx._source.test: []', is a bad expression as the left hand side of an assignment operator at line: 1 column: 82. File: a8220b2cf14b8b7ebeead7f068416882d04fa25d @ line 1, column 82.\n   CILastCallResultRemark ?: []) += remarkI\n                                 ^\n\n1 error\n"
            }
        }
    }
},
"status": 400
}

编辑

现在,我想添加一个字段以确保更新或插入对象。 例如:

{
    "test":[{"remark":"remark1","id":"1"}]
}

当我更新字段时,当id存在时,我会更新对象。相反,我会插入对象。

【问题讨论】:

  • @Val { "script": "ctx._source.test= ((ctx._source.test?: []) += remarkItem)", "params": { "remarkItem": { "remark": "addd" } } }..这个脚本有错误。为什么?
  • 请用您尝试过的内容和遇到的错误更新您的问题。
  • @Val,我编辑了内容。
  • +替换+=

标签: elasticsearch


【解决方案1】:

我建议尝试这样的脚本,它在参数中接受两个参数。它将检查任何嵌套对象是否已经包含给定的 id:

  • 如果是,它将更新给定的remark
  • 如果没有,它将在test 数组中插入一个新的嵌套对象。

脚本如下:

def updated = false
ctx._source.test?.each { obj -> 
    if (obj.id == item.id) { 
        obj.remark = item.remark
        updated = true
    } 
}
if (!updated) {
    ctx._source.test = ((ctx._source.test ?: []) + item)
}

内联并使用适当的分号后,脚本如下所示:

{
    "script": "def updated = false; ctx._source.test?.each { obj -> if (obj.id == item.id) { obj.remark = item.remark; updated = true } }; if (!updated) { ctx._source.test = ((ctx._source.test ?: []) + item)}",
    "params": {
        "item": {
            "remark": "addd",
            "id": "1"
        }
    }
}

【讨论】:

  • { "script": "ctx._source.CILastCallResultRemark?.each { obj -> if (obj.id == item.id) {obj = null } }", "params": { "item": { "id": "2" } } },为什么这个脚本不能删除对象?
  • obj = null 不会删除对象,而只是将其设置为 null。要删除对象,您需要执行不同的脚本。
  • 您或许应该创建另一个问题,因为原始问题已解决。我们可能不想在这个线程中塞进太多东西。
  • 我创建一个新问题。stackoverflow.com/questions/36614880/… 谢谢。
  • 我可以运行这个脚本,并且脚本会显示成功消息,但是当我去查看 elasticsearch 记录时,数据没有更新为 elasticsearch 数据
猜你喜欢
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
  • 2016-04-03
相关资源
最近更新 更多