Elasticsearch:更新/更新文档内的数组字段,但忽略某些现有字段

时间:2020-03-03 03:45:52

标签: elasticsearch elasticsearch-painless

获取_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 }

上面的问题是,当我运行批量更新脚本时,它将替换该文档字段,从而删除了add_vals列表。我可以使用轻松的脚本来实现这一目标吗?谢谢。

1 个答案:

答案 0 :(得分:0)

使用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而不是null进行检查。

相关问题