Elasticsearch 聚合學習之四:結果排序
歡迎訪問我的 GitHub
這裡分類和彙總了欣宸的全部原創(含配套原始碼): http://github.com/zq2599/blog_demos
本篇概覽
-
本文是《Elasticsearch 聚合學習》系列的第四篇,在前面的實戰中,聚合的結果以桶(bucket)為單位,放在 JSON 陣列中返回,這些資料是沒有排序的,今天來學習如何給這些資料進行排序;
系列文章列表
環境資訊
-
以下是本次實戰的環境資訊,請確保您的 Elasticsearch 可以正常執行:
-
作業系統:Ubuntu 18.04.2 LTS
-
JDK:1.8.0_191
-
Elasticsearch:6.7.1
-
Kibana:6.7.1
-
實戰用的資料依然是一些汽車銷售的記錄,在第一章有詳細的匯入步驟,請參考操作,匯入後您的 es 中的資料如下圖:
-
接下來一起實戰聚合排序吧;
預設排序
-
之前文章中的聚合查詢,我們都沒有做排序設定,此時 es 會用每個桶的 doc_count 欄位做降序,下圖是個 terms 桶聚合的示例,可見返回了三個 bucket 物件,是按照 doc_count 欄位降序排列的:
內建排序
-
除了自定義排序,es 自身也內建了兩種排序引數,可以直接拿來使用:
-
_count:這個引數對應的就是 doc_count,以下請求的排序效果和預設的排序效果是一致的:
GET /cars/transactions/_search
{
"size":0,
"aggs":{
"popular_colors":{
"terms": {
"field": "color",
"order": { ---表示要對聚合結果做排序
"_count": "desc" ---排序欄位是doc_count,順序是降序
}
}
}
}
}
複製程式碼
-
_key:在區間聚合的時候(histogram 或者 date_histogram),可以根據桶的 key 做排序:
GET /cars/transactions/_search
{
"size": 0,
"aggs": {
"price": {
"histogram": { ---區間聚合
"field": "price", ---取price欄位的值
"interval": 20000, ---每個區間的大小是20000
"order": { ---表示要對聚合結果做排序
"_key": "desc" ---排序欄位是桶的key值,這裡是每個區間的起始值,順序是降序
}
}
}
}
}
複製程式碼
-
返回結果如下,已經按照 key 的大小從大到小排序:
......
"aggregations" : {
"price" : {
"buckets" : [
{
"key" : 80000.0,
"doc_count" : 1
},
{
"key" : 60000.0,
"doc_count" : 0
},
{
"key" : 40000.0,
"doc_count" : 0
},
{
"key" : 20000.0,
"doc_count" : 4
},
{
"key" : 0.0,
"doc_count" : 3
}
]
}
}
}
複製程式碼
-
《Elasticsearch 權威指南》 裡指出:**_key**只在 histogram 和 date_histogram 內使用,原文如下圖紅框所示:
-
但是在實際操作中發現,6.7.1 版本中,除了 histogram 和 date_histogram,terms 桶也可以用**_key**排序,如下圖,是按照 key 的字母降序:
-
把 desc 改為 asc 之後返回如下圖,變成了按照 key 的首字母升序排序:
-
另外 《Elasticsearch 權威指南》 中還提到一種內建排序型別**_term**,但是 《Elasticsearch官方文件》 中宣佈該型別在 6.0 之後已經廢棄,如下:
-
也許是"手賤"的緣故,我還是用_term 試了下,可以返回結果,但是會建議用_key 替代_term,如下圖:
-
按照 metrics 排序(metrics 結果只有一個值)
-
常見的 metrics 有累加和(sum)、最大值(max)、最小值(min)、平均值(avg),這些 metrics 的特點是處理結果只有一個值,我們可以按照這個結果來排序,例如計算每個汽車品牌的銷售額,再按照銷售額排序:
GET /cars/transactions/_search
{
"size": 0,
"aggs": {
"sales_rank": {
"terms": { ---桶型別是terms
"field": "make", ---按照make欄位聚合
"order": { ---要求排序
"sales": "desc" ---排序欄位是sales
}
},
"aggs": {
"sales": { ---metrics處理後的結果儲存在名為sales的欄位中,排序已經指定了該欄位
"sum": { ---桶內的metrics處理,型別是累加
"field": "price" ---將price欄位的值累加
}
}
}
}
}
}
複製程式碼
-
下面是聚合結果,可見已按照每個品牌的銷售額大小做了降序的排序:
......
"aggregations" : { ---聚合結果
"sales_rank" : { ---桶名稱
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ---這個JSON陣列內是按照品牌聚合而成的所有桶
{
"key" : "bmw", ---品牌為bmw的桶
"doc_count" : 1, ---文件數量為1
"sales" : { ---metrics處理結果
"value" : 80000.0 ---品牌為bmw的汽車銷售總額是80000
}
},
{
"key" : "ford",
"doc_count" : 2,
"sales" : {
"value" : 55000.0
}
},
{
"key" : "honda",
"doc_count" : 3,
"sales" : {
"value" : 50000.0
}
},
{
"key" : "toyota",
"doc_count" : 2,
"sales" : {
"value" : 27000.0
}
}
]
}
}
}
複製程式碼
按照 metrics 排序(metrics 結果有多個值)
-
和 sum、max 這些只有一個結果的 metrics 不同,extended_stats 的結果包含了數量、最大值、最小值、平均值、累加和等多種處理,此時必須要指定用其中的哪一項(否則會返回錯誤:Invalid aggregation order path [xxxx]. When ordering on a multi-value metrics aggregation a metric name must be specified):
GET /cars/transactions/_search
{
"size": 0,
"aggs": {
"sales_rank": {
"terms": { ---桶型別是terms
"field": "make", ---按照make欄位聚合
"order": { ---要求排序
"stat.avg": "asc" ---排序欄位是metrics結果的一個子項(平均值),升序
}
},
"aggs": {
"stat": { ---metrics處理後的結果儲存在名為stat的欄位中,排序已經指定了該欄位的agv子項(平均值)
"extended_stats": { ---桶內的metrics處理,型別是計算數量、最大值、最小值、平均值等多個指標項
"field": "price" ---將price欄位的值拿來做metrics處理
}
}
}
}
}
}
複製程式碼
-
返回結果如下,可見已經按照 metrics 結果的 avg 子項做了升序排序:
......
"aggregations" : {
"sales_rank" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "toyota",
"doc_count" : 2,
"stat" : {
"count" : 2,
"min" : 12000.0,
"max" : 15000.0,
"avg" : 13500.0, ---排序欄位
"sum" : 27000.0,
"sum_of_squares" : 3.69E8,
"variance" : 2250000.0,
"std_deviation" : 1500.0,
"std_deviation_bounds" : {
"upper" : 16500.0,
"lower" : 10500.0
}
}
},
{
"key" : "honda",
"doc_count" : 3,
"stat" : {
"count" : 3,
"min" : 10000.0,
"max" : 20000.0,
"avg" : 16666.666666666668, ---排序欄位
"sum" : 50000.0,
"sum_of_squares" : 9.0E8,
"variance" : 2.222222222222221E7,
"std_deviation" : 4714.045207910315,
"std_deviation_bounds" : {
"upper" : 26094.757082487296,
"lower" : 7238.5762508460375
}
}
},
......
複製程式碼
巢狀桶排序
-
在聚合查詢中,經常對聚合的資料再次做聚合處理,例如統計每個汽車品牌下的每種顏色汽車的銷售額,這時候 DSL 中就有了多層 aggs 物件的巢狀,這就是巢狀桶(此名稱來自 《Elasticsearch 權威指南》 ),如下圖所示:
-
巢狀桶的排序情況略為複雜,詳情請參考 《Elasticsearch聚合的巢狀桶如何排序》 ;
-
至此,聚合返回結果排序的實戰已經完成了,後面的章節會深入學習 es 的聚合有關的關鍵知識點;
歡迎關注 InfoQ:程式設計師欣宸
- 那些 Go 語言發展歷史上的重大決策
- 從趨勢到挑戰,一站式解讀作業系統運維和可觀測性
- 百萬級 Topic,騰訊雲的 Apache Pulsar 穩定性實踐
- Apache Doris 在思必馳的應用優化實踐:海量語音通話資料下,實時、離線一體的數倉架構設計實踐
- 愛數正式開源認知智慧開發框架 KWeaver
- 運維智慧化的三大關鍵技術
- “抄我的還‘反捅’我一刀”,Gary Marcus 發文駁斥圖靈獎得主 Yann LeCun
- 當出海成為必選項,企業如何構建全場景全生態技術底座?
- 數智底座必備能力三:快速構建創新應用
- Docker 多階段構建實戰 (multi-stage builds)
- 工作筆記之 SELECT 語句在 SAP ABAP 中的用法總結(上)
- 經久不衰的設計定律是不要讓我思考的設計
- 不要指望下一個像 GPT 這樣的大型語言模型會民主化
- Java 近期新聞:Helidon Níma、Spring Framework、MicroProfile、MicroStream、Kotlin 和 Piranha
- 一文入門 jQuery
- C 學習 ---__libc_open 函式的原理
- 監控系統工作原理
- 甲骨文新微服務框架 Helidon Níma:使用虛擬執行緒實現高效能
- 【雲原生 | 從零開始學 Kubernetes】二、使用 kubeadm 搭建 K8S 叢集
- Elasticsearch 聚合學習之四:結果排序