Elasticsearch:如何修改 nested 字段的值

Posted Elastic 中国社区官方博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch:如何修改 nested 字段的值相关的知识,希望对你有一定的参考价值。

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,现在已经被成功地移除了。

以上是关于Elasticsearch:如何修改 nested 字段的值的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch,如何使 NEST 地图响应类

如何在 NEST 中禁用驼峰式 Elasticsearch 字段名称?

如何在 NEST2 中更新 Elasticsearch 文档

ElasticSearch 和 NEST:如何从索引中清除所有文档?

如何将单个 .NET 类型映射到 ElasticSearch/NEST 中的多个嵌套对象类型?

如何在 C# Nest 中将日期值发送到 elasticsearch 聚合查询