ES7學習筆記(十)聚合查詢


聚合查詢,它是在搜索的結果上,提供的一些聚合數據信息的方法。比如:求和、最大值、平均數等。聚合查詢的類型有很多種,每一種類型都有它自己的目的和輸出。在ES中,也有很多種聚合查詢,下面我們看看聚合查詢的語法結構,

"aggregations" : {
    "<aggregation_name>" : {
        "<aggregation_type>" : {
            <aggregation_body>
        }
        [,"meta" : {  [<meta_data_body>] } ]?
        [,"aggregations" : { [<sub_aggregation>]+ } ]?
    }
    [,"<aggregation_name_2>" : { ... } ]*
}

aggregations實體包含了所有的聚合查詢,如果是多個聚合查詢可以用數組,如果只有一個聚合查詢使用對象,aggregations也可以簡寫為aggsaggregations里邊的每一個聚合查詢都有一個邏輯名稱,這個名稱是用戶自定義的,在我們的語法結構中,對應的是<aggregation_name>。比如我們的聚合查詢要計算平均價格,這時我們自定義的聚合查詢的名字就可以叫做avg_price,這個名字要在聚合查詢中保持唯一。

在自定義的聚合查詢對象中,需要指定聚合查詢的類型,這個類型字段往往是對象中的第一個字段,在上面的語法結構中,對應的是<aggregation_type>。在聚合查詢的內部,還可以有子聚合查詢,對應的是aggregations,但是只有Bucketing 類型的聚合查詢才可以有子聚合查詢。

metrics 聚合查詢

metrics 我覺得在這里翻譯成“指標”比較好,也不是太准確,我們還是用英文比較好。metrics 聚合查詢的值都是從查詢結果中的某一個字段(field)提煉出來的,下面我們就看看一些常用的metrics 聚合查詢。我們有如下的一些索引數據,大家先看一下,

索引的名字叫做bank,一些關鍵的字段有account_number銀行賬號,balance賬戶余額,firstnamelastname等,大家可以直接看出它們代表的含義。假如我們想看看銀行里所有人的平均余額是多少,那么查詢的語句該怎么寫呢?

POST /bank/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      }
    }
  },
  "aggs": {
    "avg_balance": {
      "avg": {
        "field": "balance"
      }
    }
  }
}

在查詢語句中,查詢的條件匹配的是全部,在聚合查詢中,我們自定義了一個avg_balance的聚合查詢,它的類型是avg,求平均數,然后我們指定字段是balance,也就是我們要計算平均數的字段。我們執行一下,然后看看返回的結果,

{
	"took": 11,
	"timed_out": false,
	"_shards": {
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": ……
	"aggregations": {
		"avg_balance": {
			"value": 25714.837
		}
	}
}

在返回的結果中,我們看到在aggregations中,返回了我們自定義的聚合查詢avg_balance,並且計算的平均值是25714.837

如果我們要查詢balance的最大、最小、平均、求和、數量等,可以使用stats查詢,我們來看一下如何發送這個請求,

POST /bank/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      }
    }
  },
  "aggs": {
    "stats_balance": {
      "stats": {
        "field": "balance"
      }
    }
  }
}

我們只需要把前面聚合查詢的類型改為stats就可以了,我們看一下返回的結果,

{
	"took": 20,
	"timed_out": false,
	"_shards": {
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": ……
	"aggregations": {
		"stats_balance": {
			"count": 1000,
			"min": 1011,
			"max": 49989,
			"avg": 25714.837,
			"sum": 25714837
		}
	}
}

我們可以看到在返回的結果中,返回了5個字段,我們最常用的最大、最小、平均、求和、數量都包含在內,很方便是不是。

Bucket 聚合查詢

Bucket 聚合不像metrics 那樣基於某一個值去計算,每一個Bucket (桶)是按照我們定義的准則去判斷數據是否會落入桶(bucket)中。一個單獨的響應中,bucket(桶)的最大個數默認是10000,我們可以通過serarch.max_buckets去進行調整。

如果從定義來看,理解Bucket聚合查詢還是比較難的,而且Bucket聚合查詢的種類也有很多,給大家一一介紹不太可能,我們舉兩個實際中用的比較多的例子吧。在上面的metrics 聚合中,我們可以查詢到數量(count),但是我們能不能分組呢?是不是和數據庫中的group by聯系起來了?對,Bucket 聚合查詢就像是數據庫中的group by,我們還用上面銀行的索引,比如說我們要看各個年齡段的存款人數,那么查詢語句我們該怎么寫呢?這里就要使用Bucket 聚合中的Terms聚合查詢,查詢語句如下:

POST /bank/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      }
    }
  },
  "aggs": {
    "ages": {
      "terms": {
        "field": "age"
      }
    }
  }
}

其中,ages是我們定義的聚合查詢的名稱,terms指定要分組的列,我們運行一下,看看結果,

……
{
    "aggregations": {
    "ages": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 463,
        "buckets": [
            {
                "key": 31,
                "doc_count": 61
            }
            ,
            {
                "key": 39,
                "doc_count": 60
            }
            ,
            {
                "key": 26,
                "doc_count": 59
            }
            ,
            {
                "key": 32,
                "doc_count": 52
            }
            ,
            {
                "key": 35,
                "doc_count": 52
            }
            ,
            {
                "key": 36,
                "doc_count": 52
            }
            ,
            {
                "key": 22,
                "doc_count": 51
            }
            ,
            {
                "key": 28,
                "doc_count": 51
            }
            ,
            {
                "key": 33,
                "doc_count": 50
            }
            ,
            {
                "key": 34,
                "doc_count": 49
            }
        ]
    }
}

我們可以看到在返回的結果中,每個年齡的數據都匯總出來了。假如我們要看每個年齡段的存款余額,該怎么辦呢?這里就要用到子聚合查詢了,在Bucket 聚合中,再加入子聚合查詢了,我們看看怎么寫,

POST /bank/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      }
    }
  },
  "aggs": {
    "ages": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "sum_balance": {
          "sum": {
            "field": "balance"
          }
        }
      }
    }
  }
}

我們在聚合類型terms的后面又加了子聚合查詢,在子聚合查詢中,又自定義了一個sum_balance的查詢,它是一個metrics 聚合查詢,要對字段balance進行求和。我們運行一下,看看結果。

"aggregations": {
    "ages": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 463,
        "buckets": [
            {
                "key": 31,
                "doc_count": 61,
                "sum_balance": {
                    "value": 1727088
                }
            }
            ,
            {
                "key": 39,
                "doc_count": 60,
                "sum_balance": {
                    "value": 1516175
                }
            }
            ,
            {
                "key": 26,
                "doc_count": 59,
                "sum_balance": {
                    "value": 1368494
                }
            }
            ,
            {
                "key": 32,
                "doc_count": 52,
                "sum_balance": {
                    "value": 1245470
                }
            }
            ,
            {
                "key": 35,
                "doc_count": 52,
                "sum_balance": {
                    "value": 1151108
                }
            }
            ,
            {
                "key": 36,
                "doc_count": 52,
                "sum_balance": {
                    "value": 1153085
                }
            }
            ,
            {
                "key": 22,
                "doc_count": 51,
                "sum_balance": {
                    "value": 1261285
                }
            }
            ,
            {
                "key": 28,
                "doc_count": 51,
                "sum_balance": {
                    "value": 1441968
                }
            }
            ,
            {
                "key": 33,
                "doc_count": 50,
                "sum_balance": {
                    "value": 1254697
                }
            }
            ,
            {
                "key": 34,
                "doc_count": 49,
                "sum_balance": {
                    "value": 1313688
                }
            }
        ]
    }
}

我們看到返回結果中,增加了我們定義的sum_balance字段,它是balance余額的匯總。這個例子我們應該對bucket(桶)這個概念有了一個非常形象的認識了。還有一些其他的bucket聚合查詢,這里就不給大家一一介紹了,比如:我們只想查某幾個年齡段的余額匯總,就可以使用filters-aggregation

好了,ES的一些基本的聚合查詢就給大家介紹到這里了,如果要用到一些其他的聚合查詢,可以參照ES的官方文檔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM