【问题标题】:Elasticsearch: remove/update field inside nested objectElasticsearch:删除/更新嵌套对象内的字段
【发布时间】:2021-12-31 10:25:08
【问题描述】:
{
  "_index" : "test",
  "_type" : "test",
  "_id" : "1212",
  "_version" : 5,
  "found" : true,
  "_source" : {
    "count" : 42,
    "list_data" : [ {
      "list_id" : 11,
      "timestamp" : 1469125397
    }, {
      "list_id" : 122,
      "timestamp" : 1469050965
    } ]
  }
}

这是我的文档架构。list_data 是嵌套对象。我需要更新/删除list_data 中的特定文件。我可以使用 groovy 脚本更新 count 字段。

$ curl -XPOST 'localhost:9200/index/type/1212/_update?pretty' -d '
{
    "script" : "ctx._source.count = 41"
}'

但不知道如何更新嵌套对象。

例如,我想将其添加到list_data

{
   "list_id" : 121,
   "timestamp" : 1469050965
}

我的文档应该更改为:

{
  "_index" : "test",
  "_type" : "test",
  "_id" : "1212",
  "_version" : 6,
  "found" : true,
  "_source" : {
    "count" : 41,
    "list_data" : [ {
      "list_id" : 11,
      "timestamp" : 1469125397
    }, {
      "list_id" : 121,
      "timestamp" : 1469050965
    }, {
      "list_id" : 122,
      "timestamp" : 1469050965
    } ]
  }
}

如果我根据list_id = 122 执行删除,我的记录应该是这样的

{
  "_index" : "test",
  "_type" : "test",
  "_id" : "1212",
  "_version" : 7,
  "found" : true,
  "_source" : {
    "count" : 41,
    "list_data" : [ {
      "list_id" : 11,
      "timestamp" : 1469125397
    }, {
      "list_id" : 121,
      "timestamp" : 1469050965
    }]
  }
}

【问题讨论】:

标签: elasticsearch groovy


【解决方案1】:

要向嵌套字段中添加新元素,您可以这样进行:

$ curl -XPOST 'localhost:9200/index/type/1212/_update?pretty' -d '
{
    "script" : "ctx._source.list_data += newElement",
    "params": {
        "newElement": {
           "list_id" : 121,
           "timestamp" : 1469050965
        }
    }
}'

要从嵌套字段列表中删除现有元素,您可以这样操作:

$ curl -XPOST 'localhost:9200/index/type/1212/_update?pretty' -d '
{
    "script" : "ctx._source.list_data.removeAll{it.list_id == remove_id}",
    "params": {
        "remove_id" : 122
    }
}'

【讨论】:

  • 非常感谢@Val。是否通过 Elastic java 客户端支持?如果您可以为相同的操作提供 Java 客户端代码,那就太好了。
  • 很高兴它有帮助! Java Client 官方文档中有一个例子:elastic.co/guide/en/elasticsearch/client/java-api/current/…
  • add 方法会继续添加值,即使它已经存在。我想检查list_id 是否已经存在然后只更新timestamp 值,否则添加它。如果您可以提供一些链接来学习此脚本部分,它将对我将来有所帮助。
  • 您可以通过相应地修改带有if/else 大小写的脚本来做到这一点。
  • @Val 如何更新 list_id 的时间戳,例如 list_id=121 ?
【解决方案2】:

我在使用最新版本的 ElasticSearch 7.9.0 时收到错误 [UpdateRequest] unknown field [params](写此答案时 7.9.0 是最新版本),似乎语法发生了一些变化。

以下内容应该适用于较新版本的 ElasticSearch:

$ curl -XPOST 'localhost:9200/<index-name>/_update/1212'
{
  "script": {
    "source": "ctx._source.list_data.removeIf(list_item -> list_item.list_id == params.remove_id);",
    "params": {
      "remove_id": 122
    }
  }
}

【讨论】:

    【解决方案3】:

    我不知道为什么,但我发现

    ctx._source.list_data.removeAll{it.list_id == remove_id}
    

    无法工作。相反,我像这样使用removeIf

    ctx._source.list_data.removeIf{list_item -> list_item.list_id == remove_id}
    

    list_item 可以是任意字符串。

    【讨论】:

    • 这里如何添加多个条件?
    • ctx._source.list_data.removeIf{list_item -> list_item.list_id == remove_id && list_item.list_id != ID012} 只是一个提示。
    【解决方案4】:

    对我有用的是以下link 中的说明。也许是ES的版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-14
      • 2015-06-25
      • 2018-12-30
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多