【问题标题】:Elasticsearch: Update/upsert an array field inside a document but ignore certain existing fieldsElasticsearch:更新/更新文档中的数组字段,但忽略某些现有字段
【发布时间】:2020-03-03 03:45:52
【问题描述】:

获取_doc/1

"_source": {
"documents": [
    {
        "docid": "ID001",
        "added_vals": [
            {
                "code": "123",
                "label": "Abc"
            },
            {
                "code": "113",
                "label": "Xyz"
            }
        ]
    },
    {
        "docid": "ID002",
        "added_vals": [
            {
                "code": "123",
                "label": "Abc"
            }
        ]
    }
],
"id": "1"
}

POST /_bulk

{ "update": { "_id": "1"}}
{ "doc": { "documents": [ { "docid": "ID001", "status" : "cancelled" } ], "id": "1" }, "doc_as_upsert": true }

上面的问题是当我运行批量更新脚本时,它会替换该文档字段,删除 added_vals 列表。我可以使用无痛脚本来实现这一点吗?谢谢。

【问题讨论】:

    标签: elasticsearch elasticsearch-painless


    【解决方案1】:

    使用elasticsearch painless scripting

    POST /_bulk

    { "update": { "_id": "1"} }
    { "scripted_upsert":true, "script" :{ "source": "if(ctx._version == null) { ctx._source = params; } else { def param = params; def src = ctx._source; for(s in src.documents) { boolean found = false; for(p in param.documents) { if (p.docid == s.docid) { found = true; if(s.added_vals != null) { p.added_vals = s.added_vals; } } } if(!found) param.documents.add(s); } ctx._source = param; }", "lang": "painless", "params" : { "documents": [ { "docid": "ID001", "status" : "cancelled" } ], "id": "1" } }, "upsert" : {  } } 
    

    嗯,这个对我有用。我需要调整一些我需要的东西,但我会把它留给可能需要它的人。没想到这么简单。如果有任何其他可能更容易的答案,请提交。谢谢。

    “脚本”:

    if(ctx._version == null)
    {
        ctx._source = params;
    }
    else
    {
        def param = params;    
        def src = ctx._source;
        for(s in src.documents)
        {
            boolean found = false;
            for(p in param.documents)
            {
                if (p.docid == s.docid) 
                {
                    found = true;
                    if(s.added_vals != null)
                    {
                        p.added_vals = s.added_vals;                    
                    }
                }
            }
            if(!found) param.documents.add(s);
        }
        ctx._source = param;        
    }
    

    我不确定是否应该直接修改参数,所以我使用并将参数传递给 param 变量。我还使用了 scripted_upsert: true 和 ctx._version not null 检查。

    【讨论】:

    • 请原谅 1 行 'if' 带有额外的括号,我在我的实际脚本中删除了它们,我只想显示它正确属于哪个语句。
    • 这种方法的问题......它使用参数作为新文档,它删除了其他字段。通过一些调整,您可以包含其他字段。
    • 更改 [ctx._source = 参数; ] 到 [ ctx._source.documents = param.documents; ] 仅应用更改文档列表上的更改
    猜你喜欢
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 2017-03-07
    • 2018-11-22
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多