- 數據樣例
索引名:nested
類型:doc1
{
"detail": [
{
"name": "美團",
"nid": 1200
}
],
"id": 1
}
- 添加
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.detail.add(params.data);",
"params": {
"data": {
"name": "百度",
"nid": 1300
}
}
}
}
# 數據:
{
"_index": "nested",
"_type": "doc1",
"_id": "1",
"_score": 1.0,
"_source": {
"detail": [
{
"name": "美團",
"nid": 1200
},
{
"name": "百度",
"nid": 1300
}
],
"id": 1
}
}
- 修改
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "for(e in ctx._source.detail){if (e.name == params.name) {e.nid = params.nid;}}",
"params": {
"name": "百度",
"nid": 1500
}
}
}
- 刪除
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.detail.removeIf(it -> it.nid ==params.nid);if(ctx._source.detail.length == 0){ctx.op='delete'}",
"params":{
"nid": 1200
}
}
}
# 刪除後
{
"_index": "nested",
"_type": "doc1",
"_id": "1",
"_score": 1,
"_source": {
"detail": [
{
"name": "百度",
"nid": 1500
}
],
"id": 1
}
}
這個腳本先刪除detail中nid=1200的元素,然後判斷如果detail長度爲0則刪除這條數據。
如果指定的nid不存在,也會返回200,但數據的版本號+1
- 查詢
GET /nested/doc1/_search
{
"query": {
"nested": {
"path": "detail",
"query": {
"term": {
"detail.nid": 1500
}
},
"inner_hits": {} # 返回嵌套查詢命中的文檔,可像普通查詢那樣添加from,size,_source等參數
}
}
}
- 使用腳本來獲取每條數據中嵌套類型數組的長度
{
"query": {
"match_all": {}
},
"script_fields": {
"detail_count": { # 名稱自定義
"script": {
"lang": "painless",
"source": "params['_source']['detail'].length"
}
}
},
"size": 100
}
params['_source']
和doc['xxx']
的區別:
doc
僅用於獲取簡單的(一個鍵對應一個值)、不分析的字段的值,像嵌套類型、文本類型等是不能用的。因此查詢會緩存,速度快,但也意味着更多的內存消耗。params['_source']
每次使用都要加載和解析,所以速度慢。
推薦使用doc,不能用再使用params。
注意:
腳本中應避免使用硬編碼,即使用類似下面的編寫方式:
"source": "for(e in ctx._source.detail){if (e.name == '百度') {e.nid = 1500;}}",
這將導致腳本每次運行之前都要進行編譯解析等工作,應當使用params
參數。如果腳本是固定的,可將腳本保存在es中,後續只需要傳入腳本id和參數即可。