Elasticsearch嵌套对象管理

Elasticsearch嵌套对象管理

1. 索引包括嵌套对象、

嵌套对象能够表达关系型数据库中一对多关系,同时加强检索能力。下面定义human索引包括cats嵌套对象,定义mapping:web

PUT human
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "cats": {
        "type": "nested",
        "properties": {
          "colors": {
            "type": "integer"
          },
          "name": {
            "type": "text"
          },
          "breed": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

Human有name属性和嵌套对象cats;cats包括下面三个属性:colors,name,breed数据库

下面增长一个文档带有三个cat:api

PUT /human/_doc/1
{
  "name": "iridakos",
  "cats": [
    {
      "colors": 1,
      "name": "Irida",
      "breed": "European Shorthair"
    },
    {
      "colors": 2,
      "name": "Phoebe",
      "breed": "European"
    },
    {
      "colors": 3,
      "name": "Nino",
      "breed": "Aegean"
    }
  ]
}

查询文档确认添加:app

GET /human/_doc/1

返回结果:svg

{
  "_index" : "human",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "iridakos",
    "cats" : [
      {
        "colors" : 1,
        "name" : "Irida",
        "breed" : "European Shorthair"
      },
      {
        "colors" : 2,
        "name" : "Phoebe",
        "breed" : "European"
      },
      {
        "colors" : 3,
        "name" : "Nino",
        "breed" : "Aegean"
      }
    ]
  }
}

2. 维护嵌套对象

下面讨论如何对嵌套对象进行添加、修改、删除。code

2.1. 添加嵌套对象

增长一个嵌套对象Leon。使用_updateapi:xml

POST /human/_update/1
{
  "script": {
    "source": "ctx._source.cats.add(params.cat)",
    "params": {
      "cat": {
        "colors": 4,
        "name": "Leon",
        "breed": "Persian"
      }
    }
  }
}

经过ctx._source.cats访问嵌套对象,返回collection,执行add方法增长新的cat。新cat属性经过params传入。对象

2.2. 删除嵌套对象

咱们如今删除cat集合中删除Nino:索引

POST /human/_update/1
{
  "script": {
    "source": "ctx._source.cats.removeIf(cat -> cat.name == params.cat_name)",
    "params": {
      "cat_name": "Nino"
    }
  }
}

经过ctx._source.cats返回集合,经过removeIf方法有条件删除条目。removeIf方法参数为Predicate,肯定是否要删除特定条目。predicate在集合中每一个条目上执行,返回值为Boolean,true则删除,咱们示例经过判断name属性使用与参数cat_name相同。ip

2.3. 修改嵌套对象

修改全部cat的属性breeds 为 European 修改成 European Shorthair:

POST /human/_update/1
{
  "script": {
    "source": "def targets = ctx._source.cats.findAll(cat -> cat.breed == params.current_breed); for(cat in targets) { cat.breed = params.breed }",
    "params": {
      "current_breed": "European",
      "breed": "European Shorthair"
    }
  }
}

ctx._source.cats返回集合,在集合上执行findAll方法选择想要的条目,Predicate参数设定条件。查询内容和修改内容都经过参数传入。

2.4. 运用多个条件更新多个属性

如今使用更加灵活脚本实现更复杂的示例。目标对象须要多个条件进行匹配,更新多个属性。
加入咱们想修改cat属性breed为Persian,colors为3,修改成Aegean和3 。脚本以下:

POST /human/_update/1
{
  "script": {
    "source": "def targets = ctx._source.cats.findAll(cat -> { for (condition in params.conditions.entrySet()) { if (cat[condition.getKey()] != condition.getValue()) { return false; } } return true; }); for (cat in targets) { for (change in params.changes.entrySet()) { cat[change.getKey()] = change.getValue() } }",
    "params": {
      "conditions": {
        "breed": "Persian",
        "colors": 4
      },
      "changes": {
        "breed": "Aegean",
        "colors": 3
      }
    }
  }
}

格式化代码:

def targets = ctx._source.cats.findAll(cat -> {
                                         for (condition in params.conditions.entrySet()) {
                                           if (cat[condition.getKey()] != condition.getValue()) {
                                             return false;
                                           }
                                         }
                                         return true; });
for (cat in targets) {
 for (change in params.changes.entrySet()) {
   cat[change.getKey()] = change.getValue()
 }
}

经过params.conditions参数肯定条件查询目标对象,经过params.changes参数传入修改后的值。

3. 总结

本文介绍Elasticsearch的嵌套对象,经过示例说明如何使用脚本维护嵌套对象。