如何管理es索引中的嵌套对象

本文介绍了如何在Elasticsearch中管理索引中的嵌套对象,包括创建索引、添加、删除、更新嵌套对象以及满足多个条件更新多个属性的操作,并提供了相关参考链接。
摘要由CSDN通过智能技术生成

本文摘录自:How to manage nested objects in Elasticsearch documents

Preparation(准备)

The document of our index will represent a human and its nested objects will be cats (no surprises).

Create the index(创建索引)

Open your Kibana dev console and type the following to create the index.

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

Human has:(人有如下属性)

  • a name property of type text
  • a cats property of type nested

Each cat has:(猫有如下属性)

  • a colors property of type integer
  • a name property of type text
  • a breed property of type text

Add a human(添加一个“人”的记录)

In the Kibana console, execute the following to add a human with three cats.

# Index a human
POST iridakos_nested_objects/human/1
{
  "name": "iridakos",
  "cats": [
    {
      "colors": 1,
      "name": "Irida",
      "breed": "European Shorthair"
    },
    {
      "colors": 2,
      "name": "Phoebe",
      "breed": "European"
    },
    {
      "colors": 3,
      "name": "Nino",
      "breed": "Aegean"
    }
  ]
}

Confirm the insertion with:

GET iridakos_nested_objects/human/1

You should see something like this:

{
  "_index": "iridakos_nested_objects",
  "_type": "human",
  "_id": "1",
  "_version": 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"
      }
    ]
  }
}

Done, moving on.

Managing nested objects(管理嵌套对象)

Add a new nested object(新增一个嵌套对象)

Suppose that iridakos got a new Persian cat named Leon. To add it in iridakos’ collection of cats we will use the Update API.

In Kibana:

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

Notes:

  • We accessed the nested cat objects of our human with ctx._source.cats. This gave us a collection
  • We executed the add method on the collection to add a new cat
  • The properties of the new cat (params.cat) were passed as parameters in the params attribute of the request under the attribute cat.

Confirm the addition with:

GET iridakos_nested_objects/human/1

Cat added:

{
  "_index": "iridakos_nested_objects",
  "_type": "human",
  "_id": "1",
  "_version": 2,
  "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"
      },
      {
        "colors": 4,
        "name": "Leon",
        "breed": "Persian"
      }
    ]
  }
}

Remove a nested object(删除一个嵌套对象)

Suppose we want to remove Nino from the human’s cat collection.

In Kibana:

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

Notes:

  • We accessed the nested cat objects of our human with ctx._source.cats. This gave us a collection
  • We executed the removeIf method on the collection to conditionally remove an item
  • We provided a Predicate to the removeIf method in which we specify which items we want to remove. This predicate will be executed on each item of the collection and resolves to a Boolean value. If the resolution is true then the item will be removed. In our case, the condition is a simple equality check on the cat’s name attribute.
  • The cat_name was passed as a parameter (params.cat_name) instead of fixing it to the script source.

Confirm the addition with:

GET iridakos_nested_objects/human/1

Cat removed:

{
  "_index": "iridakos_nested_objects",
  "_type": "human",
  "_id": "1",
  "_version": 3,
  "found": true,
  "_source": {
    "name": "iridakos",
    "cats": [
      {
        "colors": 1,
        "name": "Irida",
        "breed": "European Shorthair"
      },
      {
        "colors": 2,
        "name": "Phoebe",
        "breed": "European"
      },
      {
        "colors": 4,
        "name": "Leon",
        "breed": "Persian"
      }
    ]
  }
}

Update a nested object(更新一个嵌套对象)

Suppose we want to change all cat breeds from European to European Shorthair (Phoebe is the only one in our case).

# Update breed
POST iridakos_nested_objects/human/1/_update
{
  "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"
    }
  }
}

Notes:

  • We accessed the nested cat objects of our human with ctx._source.cats. This gave us a collection
  • We executed the findAll method on the collection to select specific items
  • We provided a Predicate to the findAll method in which we specify which items we want to select. This predicate will be executed on each item of the collection and resolves to a Boolean value. If the resolution is true then the item will be selected. In our case, the condition is a simple equality check on the cat’s breed attribute.
  • The current_breed was passed as a parameter (params.current_breed) instead of fixing it to the script source.
  • We then loop on the selected cats (whose breed attribute has value European) and change their breed to the new value which we passed by another parameter breed.

Confirm the change:

GET iridakos_nested_objects/human/1

Cat updated:

{
  "_index": "iridakos_nested_objects",
  "_type": "human",
  "_id": "1",
  "_version": 5,
  "found": true,
  "_source": {
    "name": "iridakos",
    "cats": [
      {
        "colors": 1,
        "name": "Irida",
        "breed": "European Shorthair"
      },
      {
        "colors": 2,
        "name": "Phoebe",
        "breed": "European Shorthair"
      },
      {
        "colors": 4,
        "name": "Leon",
        "breed": "Persian"
      }
    ]
  }
}

Update multiple attributes of nested objects fulfilling multiple conditions(更新多个嵌套对象的多个属性)

Now, in a more advanced example, we are going to use a more flexible script to:

  • target objects based on multiple conditions (here colors and breed)
  • update more than one attributes (here colors and breed)

Suppose we want to change the breed of cats who have 4 colors and their breed is Persian to Aegean and their colors to 3.

The script we will use is the following:

# Update multiple attributes with multiple conditions
POST iridakos_nested_objects/human/1/_update
{
  "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
      }
    }
  }
}

For convenience, here’s the script source with proper indentation.

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()
 }
}

Notes:

  • We select which cats we want to update by checking that their properties have the value specified in the params.conditions parameter.
  • For each selected cat, we change its attributes’ values as specified in the params.changes parameter.

Confirm:

GET iridakos_nested_objects/human/1

Cat updated.

{
  "_index": "iridakos_nested_objects",
  "_type": "human",
  "_id": "1",
  "_version": 5,
  "found": true,
  "_source": {
    "name": "iridakos",
    "cats": [
      {
        "colors": 1,
        "name": "Irida",
        "breed": "European Shorthair"
      },
      {
        "colors": 2,
        "name": "Phoebe",
        "breed": "European Shorthair"
      },
      {
        "name": "Leon",
        "colors": 3,
        "breed": "Aegean"
      }
    ]
  }
}

Useful links(参考链接)

Elasticsearch reference - Mapping - Field datatypes - Nested datatype
Elasticsearch reference - Document APIs - Update API
Elasticsearch reference - Painless API reference
That’s all! Cat photo.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值