Elastic search中使用nested類型的內嵌對象

在大數據的應用環境中,每每使用反範式設計來提升讀寫性能。
假設咱們有個相似簡書的系統,系統裏有文章,用戶也能夠對文章進行讚揚。在關係型數據庫中,若是按照數據庫範式設計,須要兩張表:一張文章表和一張讚揚歷史記錄表,讚揚歷史記錄表包括了讚揚者姓名和讚揚金額。
在Elastic search中,因爲都是json格式存儲,則能夠在一個index存儲系統中的文章及其讚揚記錄,這種狀況下須要在elastic search中使用nested類型的內嵌對象。由於若是使用數組或者object對象的話,讚揚者姓名和讚揚金額是相互獨立的進行存儲,不能被正確的關聯。html

創建index

PUT articles
{
  "mappings": { "doc": { "properties": { "payment": { "type": "nested", "properties": { "amount": { "type": "integer" }, "name": { "type": "keyword" } } } } } } } 

這樣articles就有了payment這個nested類型的字段,payment裏面的對象有amount和name,表示金額和姓名。數據庫

產生數據

產生以下數據,表示jack給文章1讚揚了29元,ross給文章1讚揚30元,ross給文章2讚揚31元。json

POST articles/doc/1
{
  "payment": [ { "name": "jack", "amount": 29 }, { "name": "ross", "amount": 30 } ] } POST articles/doc/2 { "payment": [ { "name": "ross", "amount": 31 } ] } 

根據內嵌對象進行查詢

如今想查詢ross讚揚過的文章,須要使用nested query數組

GET articles/_search
{
  "query": { "nested": { "path": "payment", "query": { "term": { "payment.name": { "value": "ross" } } } } } } 

path表示了nested字段的名稱,須要注意的是,查詢語句中要指定查詢字段的全名,因此讚揚者姓名要用"payment.name"
若是在多個index上進行nested查詢,沒有nested字段的index會報錯,這時能夠將ignore_unmapped設置爲truebash

nested對象聚合

若是想查看讚揚的平均金額,須要用nested aggregationapp

GET articles/_search
{
  "size": 0, "aggs": { "nested": { "nested": { "path": "payment" }, "aggs": { "amount_avg": { "avg": { "field": "payment.amount" } } } } } } 

一樣注意要用path指定字段名稱。返回的數據中,比普通的聚合查詢多了一層嵌套
返回結果爲elasticsearch

{
  "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 2, "max_score": 0, "hits": [] }, "aggregations": { "nested": { "doc_count": 3, "amount_avg": { "value": 30 } } } } 

nested對象聚合和過濾

若是想看ross讚揚過的總金額,一開始寫出query以下ide

GET articles/_search
{
  "size": 0, "query": { "nested": { "path": "payment", "query": { "term": { "payment.name": { "value": "ross" } } } } }, "aggs": { "nested": { "nested": { "path": "payment" }, "aggs": { "sum": { "sum": { "field": "payment.amount" } } } } } } 

此時結果並非正確的,由於上面的query過濾的是ross讚揚過的文章,下面的聚合操做sum的是文章裏全部的讚揚,包括了jack的讚揚。
因此須要在sum聚合操做以前,須要用Filter Aggregation篩選ross的讚揚。性能

GET articles/_search
{
  "size": 0, "query": { "nested": { "path": "payment", "query": { "term": { "payment.name": { "value": "ross" } } } } }, "aggs": { "payment": { "nested": { "path": "payment" }, "aggs": { "payer": { "filter": { "term": { "payment.name": { "value": "ross" } } }, "aggs": { "sum": { "sum": { "field": "payment.amount" } } } } } } } } 

最外層的query篩選出ross讚揚過的文章。
第一層的aggs表示進行內嵌聚合。
第二層的aggs用Filter Aggregation篩選出表示ross讚揚行爲的nested對象。
第三層的aggs進行聚合。大數據

做者:大神帶我來搬磚 連接:https://www.jianshu.com/p/d685b7b6c9d1 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索