当前位置: 代码网 > it编程>游戏开发>ar > Elasticsearch:如何修改 nested 字段的值

Elasticsearch:如何修改 nested 字段的值

2024年08月03日 ar 我要评论
Nested 类型是数据类型的特殊版本,它允许对象数组以一种可以彼此独立查询的方式进行索引。在内部,嵌套对象将数组中的每个对象索引为单独的隐藏文档,这意味着每个嵌套对象都可以使用独立于其他对象进行查询。每个 nested 对象都被索引为一个单独的 Lucene 文档。有关更多关于 nested 数据类型的文档,我们可以参考之前的文章 “在使用 Elasticsearch 时,为了系统的效率,我们并不建议经常修改文档,但是在有些时候,我们还必须对已经索引过的文档进行修改。

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) {
        ctx._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 < params.skills.length; i++) {
          ctx._source.skills.removeif(a->
            a.language.equals(params.skills[i].language) &&
            a.level.equals(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,现在已经被成功地移除了。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com