удалить объекты из массива эластичного поиска

Мне потребовалось удалить объект из массива, который удовлетворяет условию, я могу обновить объект массива на основе следующего условия:

PUT twitter/twit/1
{"list": 
     [
        {
            "tweet_id": "1",
            "a": "b"
        },
        {
            "tweet_id": "123",
            "a": "f"
        }
    ]
}

POST /twitter/twit/1/_update
{"script":"foreach (item :ctx._source.list) {
                if item['tweet_id'] == tweet_id) {
                      item['new_field'] = 'ghi';
                }
           }",
 "params": {tweet_id": 123"}
}

это работает

для удаления я делаю это

POST /twitter/twit/1/_update
{ "script": "foreach (item : ctx._source.list) {
                    if item['tweet_id'] == tweet_id) {
                          ctx._source.list.remove(item); 
                    }
            }",
  "params": { tweet_id": "123" }
}

но это не работает и дает эту ошибку,

ElasticsearchIllegalArgumentException [не удалось выполнить скрипт]; вложенные: ConcurrentModificationException; Ошибка: ElasticsearchIllegalArgumentException [не удалось выполнить скрипт]; вложенный: ConcurrentModificationException

Я могу удалить весь массив или все поле, используя

"script": "ctx._source.remove('list')"

Я также могу удалить объект из массива, указав все ключи объекта, используя

"script":"ctx._source.list.remove(tag)",
     "params" : {
        "tag" : {"tweet_id": "123","a": "f"}

моя версия эластичного поиска модуля узла - 2.4.2, эластичный поисковый сервер - 1.3.2


person Rajit Garg    schedule 08.10.2014    source источник


Ответы (2)


Вы получаете это, потому что вы пытаетесь изменить список во время итерации по нему, что означает, что вы хотите изменить список объектов и, в то же время, перечислить эти объекты.

Вместо этого вам нужно сделать это:

POST /twitter/twit/1/_update
{
  "script": "item_to_remove = nil; foreach (item : ctx._source.list) { if (item['tweet_id'] == tweet_id) { item_to_remove=item; } } if (item_to_remove != nil) ctx._source.list.remove(item_to_remove);",
  "params": {"tweet_id": "123"}
}

Если у вас есть несколько элементов, соответствующих критериям, используйте вместо этого список:

POST /twitter/twit/1/_update
{
  "script": "items_to_remove = []; foreach (item : ctx._source.list) { if (item['tweet_id'] == tweet_id) { items_to_remove.add(item); } } foreach (item : items_to_remove) {ctx._source.list.remove(item);}",
  "params": {"tweet_id": "123"}
}
person Andrei Stefan    schedule 08.10.2014
comment
Спасибо, Андрей Стефан, это работает, если список содержит только один объект tweet_id = 123, но это не работает, если я хочу удалить несколько объектов с одинаковым tweet_id = 123, что мне нужно для этого сделать ??? - person Rajit Garg; 09.10.2014
comment
Кроме того, я был бы признателен, если бы вы проголосовали за ответ. - person Andrei Stefan; 09.10.2014
comment
Большое спасибо, Андрей Стефан, Сейчас это работает, после этого я очень счастлив, так как вчера я потратил на это почти весь день, Еще раз спасибо .... - person Rajit Garg; 09.10.2014
comment
как я могу узнать, что в списке есть метод remove, есть ли в нем append - person jiamo; 24.08.2015

Для людей, которым это нужно для работы в elasticsearch 2.0 и выше, nil и foreach не распознаются groovy.

Итак, вот обновленная версия, включая возможность замены элемента с тем же идентификатором новым объектом.

а также передавая ему upsert, элемент будет добавлен, даже если документ еще не существует

{
  "script": "item_to_remove = null; ctx._source.delivery.each { elem -> if (elem.id == item_to_add.id) { item_to_remove=elem; } }; if (item_to_remove != null) ctx._source.delivery.remove(item_to_remove); if (item_to_add.size() > 1) ctx._source.delivery += item_to_add;",
  "params": {"item_to_add": {"id": "5", "title": "New item"}},
  "upsert": [{"id": "5", "title": "New item"}]
}
person Ludo - Off the record    schedule 29.06.2016
comment
Не могли бы вы также добавить язык канавок для удаления более одного значения в виде списка вместо одного удаления? - person Joshua I; 25.10.2016