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