【问题标题】:remove objects from array elastic search从数组弹性搜索中删除对象
【发布时间】:2014-10-08 13:16:08
【问题描述】:

我需要从数组中删除满足条件的对象,我可以根据条件更新数组的对象,如下:

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[执行脚本失败]; 嵌套:并发修改异常;错误: 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

【问题讨论】:

    标签: node.js elasticsearch mvel


    【解决方案1】:

    您之所以会这样,是因为您在迭代列表时尝试修改列表,这意味着您想要更改对象列表并同时列出这些对象。

    您需要这样做:

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

    【讨论】:

    • 感谢 Andrei Stefan,如果列表仅包含一个 tweet_id = 123 的对象,这是可行的,但这是行不通的,如果我想删除多个具有相同 tweet_id = 123 的对象,我需要什么这样做???
    • 另外,如果你能支持答案,我将不胜感激。
    • 非常感谢 Andrei Stefan,现在正在工作,在此之后我很高兴,因为昨天我花了几乎整整一天的时间,再次感谢您......
    • 我怎么知道列表有`remove`方法,有append
    【解决方案2】:

    对于需要在 elasticsearch 2.0 及更高版本中工作的人,groovy 无法识别 nilforeach

    所以这是一个更新版本,包括一个用新对象替换具有相同 id 的项目的选项。

    并将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"}]
    }
    

    【讨论】:

    • 您能否也添加凹槽语言以将多个值作为列表删除而不是单个删除?
    猜你喜欢
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 2017-09-25
    相关资源
    最近更新 更多