Elasticsearch: обновить / вставить поле массива внутри документа, но игнорировать некоторые существующие поля - PullRequest
0 голосов
/ 03 марта 2020

GET _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 голосов
/ 03 марта 2020

Использование безболезненного сценария эластичного поиска

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" : {  } } 

хорошо, этот работал для меня. Мне нужно настроить еще несколько вещей, которые мне требуются, но я оставлю это здесь для того, кому это может понадобиться. Не знал, что это было так просто. Если есть какой-либо другой ответ, который может быть проще, пожалуйста, отправьте его. Спасибо.

"script":

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...