Elasticsearch:如何修改 nested 字段的值

2023年2月20日   |   by mebius

tgcode

Nested 类型是 object 数据类型的特殊版本,它允许对象数组以一种可以彼此独立查询的方式进行索引。在内部,嵌套对象将数组中的每个对象索引为单独的隐藏文档,这意味着每个嵌套对象都可以使用 nested query 独立于其他对象进行查询。每个 nested 对象都被索引为一个单独的 Lucene 文档。有关更多关于 nested 数据类型的文档,我们可以参考之前的文章 “Elasticsearch: object 及 nested 数据类型”。

在使用 Elasticsearch 时,为了系统的效率,我们并不建议经常修改文档,但是在有些时候,我们还必须对已经索引过的文档进行修改。针对 nested 类型的字段,我该如何进行更新及删除呢?

让我们先使用一个例子来进行展示。

我们首先来创建一个 developer 的索引:

PUT developer
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "skills": {
        "type": "nested",
        "properties": {
          "language": {
            "type": "keyword"
          },
          "level": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

在上面,我们定义 skills 为一个 nested 数据类型。我们使用如下的命令来创建两个文档:

POST developer/_doc/101
{
  "name": "zhang san",
  "skills": [
    {
      "language": "ruby",
      "level": "expert"
    },
    {
      "language": "javascript",
      "level": "beginner"
    }
   ]
}
 
POST developer/_doc/102
{
  "name": "li si",
  "skills": [
    {
      "language": "ruby",
      "level": "beginner"
    }
   ]
}

上面的命令写入了两个文档。

添加技能

针对第二个文档,我们想增加如下的一个技能:

{
   "language": "Python",
    "level" "expert"
}

首先让我们使用 painless 语言创建我们的脚本。 你可以在参考资料中阅读有关它的更多详细信息,但熟悉 Java 的人会发现编码很简单。关于 painless 语音的编程,你可以在文章 “Elastic:开发者上手指南” 中的 “Painless 编程” 章节中找到很多文章进行参考。

我们的脚本将验证 skills 字段是否为空,如果是,我们创建列表实例并稍后添加新项目。如果不是,则添加新 skills。

      if (ctx._source.skills != null) {
         ctx._source.skills.addAll(params.skills);
      } else {
        ctx._source.skills = new ArrayList();
        ctx._source.skills.addAll(params.skills);
      }

最终添加 skills 的代码是这样的:

POST developer/_update/102
{
  "script": {
    "source": """
      if (ctx._source.skills != null) {
        ctxtgcode._source.skills.addAll(params.skills);
      } else {
        ctx._source.skills = new ArrayList();
        ctx._source.skills.addAll(params.skills);
      }
    """,
    "params": {
      "skills": [
          {
            "language": "Python",
            "level": "expert"
          }
       ]
    }
  }
}

我们通过如下的命令来进行验证:

GET developer/_doc/102

我们得到如下的结果:

{
  "_index": "developer",
  "_id": "102",
  "_version": 3,
  "_seq_no": 4,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "name": "li si",
    "skills": [
      {
        "language": "ruby",
        "level": "beginner"
      },
      {
        "level": "expert",
        "language": "Python"
      }
    ]
  }
}

从上面,我们可以看出来新的 skills 已经被添加进去了。

删除 skills

同样,我们可以使用如下的代码来删除一个技能:

POST developer/_update/102
{
  "script": {
    "source": """
      if (ctx._source.skills != null) {
        for (int i; i 
            a.language.equals(params.skills[i].language) &&
            a.level.eqtgcodeuals(params.skills[i].level));
        }
      }
    """,
    "params": {
      "skills": [
        {
          "language": "Python",
          "level": "expert"
        }
      ]
    }
  }
}

我们再次使用如下的命令来查看 id 为 102 的文档:

GET developer/_doc/102

上面的命令返回的值为:

{
  "_index": "developer",
  "_id": "102",
  "_version": 4,
  "_seq_no": 5,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "name": "li si",
    "skills": [
      {
        "language": "ruby",
        "level": "beginner"
      }
    ]
  }
}

我们可以看出来,在上一步添加的 skill,现在已经被成功地移除了。

文章来源于互联网:Elasticsearch:如何修改 nested 字段的值

相关推荐: Kibana:圣诞老人使用 Kibana Dashboards 驾驶他的雪橇!

又到了每年一度的圣诞节了。圣诞老人今年开始向各个国家发放礼物了。他驾驶着自己的雪橇挨个国家发放礼物了。我们收集了去世界过个国家的首都的地理位置信息,并按照一定的顺序来发放礼物。我们可以轻松地使用 Elastic Stack 中的 Kibana 来创建一个 Ma…