Elasticsearch嵌套對象管理

Elasticsearch嵌套對象管理

1. 索引包括嵌套對象、

嵌套對象可以表達關係型數據庫中一對多關係,同時增強檢索能力。下面定義human索引包括cats嵌套對象,定義mapping:

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:

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"
    }
  ]
}

查詢文檔確認添加:

GET /human/_doc/1

返回結果:

{
  "_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. 維護嵌套對象

下面討論如何對嵌套對象進行添加、修改、刪除。

2.1. 添加嵌套對象

增加一個嵌套對象Leon。使用_updateapi:

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相同。

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的嵌套對象,通過示例說明如何使用腳本維護嵌套對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章