Elasticsearch聚合查詢

聚合 aggregations

聚合可以讓我們極其方便的實現對數據的統計、分析。例如:

  • 什么品牌的手機最受歡迎?
  • 這些手機的平均價格、最高價格、最低價格?
  • 這些手機每月的銷售情況如何?

1、基本概念

Elasticsearch中的聚合,包含多種類型,最常用的兩種,一個叫,一個叫度量

桶(bucket)

桶的作用,是按照某種方式對數據進行分組,每一組數據在ES中稱為一個,例如我們根據品牌對手機劃分,可以得到小米桶華為桶蘋果桶……或者我們按照年齡段對人進行劃分:010,1020,2030,3040等。

Elasticsearch中提供的劃分桶的方式有很多:

  • Date Histogram Aggregation:根據日期階梯分組,例如給定階梯為周,會自動每周分為一組
  • Histogram Aggregation:根據數值階梯分組,與日期類似
  • Terms Aggregation:根據詞條內容分組,詞條內容完全匹配的為一組
  • Range Aggregation:數值和日期的范圍分組,指定開始和結束,然后按段分組
  • ……

綜上所述,我們發現bucket aggregations 只負責對數據進行分組,并不進行計算,因此往往bucket中往往會嵌套另一種聚合:metrics aggregations即度量

度量(metrics)

分組完成以后,我們一般會對組中的數據進行聚合運算,例如求平均值、最大、最小、求和等,這些在ES中稱為度量

比較常用的一些度量聚合方式:

  • Avg Aggregation:求平均值
  • Max Aggregation:求最大值
  • Min Aggregation:求最小值
  • Percentiles Aggregation:求百分比
  • Stats Aggregation:同時返回avg、max、min、sum、count等
  • Sum Aggregation:求和
  • Top hits Aggregation:求前幾
  • Value Count Aggregation:求總數
  • ……

為了測試聚合,我們先批量導入一些數據
創建索引:

PUT /cars
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "transactions": {
      "properties": {
        "color": {
          "type": "keyword"
        },
        "make": {
          "type": "keyword"
        }
      }
    }
  }
}

注意:在ES中,需要進行聚合、排序、過濾的字段其處理方式比較特殊,因此不能被分詞。這里我們將color和make這兩個文字類型的字段設置為keyword類型,這個類型不會被分詞,將來就可以參與聚合

導入數據

POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "吉利", "sold" : "2020-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長城", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "比亞迪", "sold" : "2020-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "比亞迪", "sold" : "2020-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "green", "make" : "長城", "sold" : "2020-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長安", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "吉利", "sold" : "2020-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "長安", "sold" : "2020-02-12" }

2 聚合為桶

首先,我們按照 汽車的顏色color來劃分

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            }
        }
    }
}
  • size: 查詢條數,這里設置為0,因為我們不關心搜索到的數據,只關心聚合結果,提高效率
  • aggs:聲明這是一個聚合查詢,是aggregations的縮寫
    • popular_colors:給這次聚合起一個名字,任意。
      • terms:劃分桶的方式,這里是根據詞條劃分
        • field:劃分桶的字段

結果:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 8,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "popular_colors": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "red",
          "doc_count": 4
        },
        {
          "key": "blue",
          "doc_count": 2
        },
        {
          "key": "green",
          "doc_count": 2
        }
      ]
    }
  }
}
  • hits:查詢結果為空,因為我們設置了size為0
  • aggregations:聚合的結果
  • popular_colors:我們定義的聚合名稱
  • buckets:查找到的桶,每個不同的color字段值都會形成一個桶
    • key:這個桶對應的color字段的值
    • doc_count:這個桶中的文檔數量

通過聚合的結果我們發現,目前紅色的小車比較暢銷!

3 桶內度量

求價格平均值的度量

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            },
            "aggs":{
                "avg_price": { 
                   "avg": {
                      "field": "price" 
                   }
                }
            }
        }
    }
}
  • aggs:我們在上一個aggs(popular_colors)中添加新的aggs。可見度量也是一個聚合,度量是在桶內的聚合
  • avg_price:聚合的名稱
  • avg:度量的類型,這里是求平均值
  • field:度量運算的字段

4 桶內嵌套桶

比如:我們想統計每種顏色的汽車中,分別屬于哪個制造商,按照make字段再進行分桶

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            },
            "aggs":{
                "avg_price": { 
                   "avg": {
                      "field": "price" 
                   }
                },
                "maker":{
                    "terms":{
                        "field":"make"
                    }
                }
            }
        }
    }
}
  • 原來的color桶和avg計算我們不變
  • maker:在嵌套的aggs下新添一個桶,叫做maker
  • terms:桶的劃分類型依然是詞條
  • filed:這里根據make字段進行劃分

5劃分桶的其它方式

  • Date Histogram Aggregation:根據日期階梯分組,例如給定階梯為周,會自動每周分為一組
  • Histogram Aggregation:根據數值階梯分組,與日期類似
  • Terms Aggregation:根據詞條內容分組,詞條內容完全匹配的為一組
  • Range Aggregation:數值和日期的范圍分組,指定開始和結束,然后按段分組
    階梯分桶Histogram
    histogram是把數值類型的字段,按照一定的階梯大小進行分組。你需要指定一個階梯值(interval)來劃分階梯大小。
    如:如果你設定interval的值為200,那么階梯就會是這樣的:
    0,200,400,600,...
GET /cars/_search
{
  "size":0,
  "aggs":{
    "price":{
      "histogram": {
        "field": "price",
        "interval": 5000
      }
    }
  }
}

計算公式

key = Math.floor((value - offset) / interval) * interval + offset
  • value:就是當前數據的值
  • offset:起始偏移量,默認為0
  • interval:階梯間隔
    min_doc_count約束最少文檔數量為1,這樣文檔數量為0的桶會被過濾
GET /cars/_search
{
  "size":0,
  "aggs":{
    "price":{
      "histogram": {
        "field": "price",
        "interval": 5000,
        "min_doc_count": 1
      }
    }
  }
}

聚合查詢并且根據字段值去重

"collapse": {
    "field": "type.keyword"
  },

示例

GET xiaomi/_search
{
  "size":10,
  "_source": ["type"],
  "collapse": {
    "field": "type.keyword"
  },
  "query": {
  "term": {
    "eventType.keyword": {
       "value": "announcement"
      }
    }
  },
  "aggs" : {
    "your_aggs" : {
    "terms" : { "field" : "type.keyword" }
    }
  }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容