1、根據color分組統計銷售數量
只執行聚合分組,不做復雜的聚合統計。在ES中最基礎的聚合為terms,相當于
SQL中的count。
在ES中默認為分組數據做排序,使用的是doc_count數據執行降序排列。可以使用
_key元數據,根據分組后的字段數據執行不同的排序方案,也可以根據_count元數
據,根據分組后的統計值執行不同的排序方案。
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_by_color": {
5 "terms": {
6 "field": "color",
7 "order": {
8 "_count": "desc"
9 }
10 }
11 }
12 }
13 }
2、統計不同color車輛的平均價格
本案例先根據color執行聚合分組,在此分組的基礎上,對組內數據執行聚合統
計,這個組內數據的聚合統計就是metric。同樣可以執行排序,因為組內有聚合統
計,且對統計數據給予了命名avg_by_price,所以可以根據這個聚合統計數據字段名
執行排序邏輯。
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_by_color": {
5 "terms": {
6 "field": "color",
7 "order": {
8 "avg_by_price": "asc"
9 }
10 },
11 "aggs": {
12 "avg_by_price": {
13 "avg": {
14 "field": "price"
15 }
16 }
17 }
18 }
19 }
20 }
size可以設置為0,表示不返回ES中的文檔,只返回ES聚合之后的數據,提高查詢速
度,當然如果你需要這些文檔的話,也可以按照實際情況進行設置
1 GET /cars/_search
2 {
3 "size" : 0,
4 "aggs": {
5 "group_by_color": {
6 "terms": {
7 "field": "color"
8 },
9 "aggs": {
10 "group_by_brand" : {
11 "terms": {
12 "field": "brand",
13 "order": {
14 "avg_by_price": "desc"
15 }
16 },
17 "aggs": {
18 "avg_by_price": {
19 "avg": {
20 "field": "price"
21 }
22 }
23 }
24 }
25 }
26 }
27 }
28 }
3、統計不同color不同brand中車輛的平均價格
先根據color聚合分組,在組內根據brand再次聚合分組,這種操作可以稱為下鉆
分析。
Aggs如果定義比較多,則會感覺語法格式混亂,aggs語法格式,有一個相對固定
的結構,簡單定義:aggs可以嵌套定義,可以水平定義。
嵌套定義稱為下鉆分析。水平定義就是平鋪多個分組方式。
1 GET /index_name/type_name/_search
2 {
3 "aggs" : {
4 "定義分組名稱(最外層)": {
5 "分組策略如:terms、avg、sum" : {
6 "field" : "根據哪一個字段分組",
7 "其他參數" : ""
8 },
9 "aggs" : {
10 "分組名稱1" : {},
11 "分組名稱2" : {}
12 }
13 }
14 }
15 }
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_by_color": {
5 "terms": {
6 "field": "color",
7 "order": {
8 "avg_by_price_color": "asc"
9 }
10 },
11 "aggs": {
12 "avg_by_price_color" : {
13 "avg": {
14 "field": "price"
15 }
16 },
17 "group_by_brand" : {
18 "terms": {
19 "field": "brand",
20 "order": {
21 "avg_by_price_brand": "desc"
22 }
23 },
24 "aggs": {
25 "avg_by_price_brand": {
26 "avg": {
27 "field": "price"
28 }
29 }
30 }
31 }
32 }
33 }
34 }
35 }
4、統計不同color中的最大和最小價格、總價
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_by_color": {
5 "terms": {
6 "field": "color"
7 },
8 "aggs": {
9 "max_price": {
10 "max": {
11 "field": "price"
12 }
13 },
14 "min_price" : {
15 "min": {
16 "field": "price"
17 }
18 },
19 "sum_price" : {
20 "sum": {
21 "field": "price"
22 }
23 }
24 }
25 }
26 }
27 }
5、統計不同品牌汽車中價格排名最高的車型
在分組后,可能需要對組內的數據進行排序,并選擇其中排名高的數據。那么可
以使用s來實現:top_top_hithits中的屬性size代表取組內多少條數據(默認為
10);sort代表組內使用什么字段什么規則排序(默認使用_doc的asc規則排序);
_source代表結果中包含document中的那些字段(默認包含全部字段)。
1 GET cars/_search
2 {
3 "size" : 0,
4 "aggs": {
5 "group_by_brand": {
6 "terms": {
7 "field": "brand"
8 },
9 "aggs": {
10 "top_car": {
11 "top_hits": {
12 "size": 1,
13 "sort": [
14 {
15 "price": {
16 "order": "desc"
17 }
18 }
19 ],
20 "_source": {
21 "includes": ["model", "price"]
22 }
23 }
24 }
25 }
26 }
27 }
28 }
6、histogram 區間統計
histogram類似terms,也是進行bucket分組操作的,是根據一個field,實現數據
區間分組。
如:以100萬為一個范圍,統計不同范圍內車輛的銷售量和平均價格。那么使用
histogram的聚合的時候,field指定價格字段price。區間范圍是100萬-interval :
1000000。這個時候ES會將price價格區間劃分為: [0, 1000000), [1000000,
2000000), [2000000, 3000000)等,依次類推。在劃分區間的同時,histogram會類似
terms進行數據數量的統計(count),可以通過嵌套aggs對聚合分組后的組內數據做
再次聚合分析。
1 GET /cars/_search
2 {
3 "aggs": {
4 "histogram_by_price": {
5 "histogram": {
6 "field": "price",
7 "interval": 1000000
8 },
9 "aggs": {
10 "avg_by_price": {
11 "avg": {
12 "field": "price"
13 }
14 }
15 }
16 }
17 }
18 }
7、date_histogram區間分組
date_histogram可以對date類型的field執行區間聚合分組,如每月銷量,每年銷
量等。
如:以月為單位,統計不同月份汽車的銷售數量及銷售總金額。這個時候可以使
用date_histogram實現聚合分組,其中field來指定用于聚合分組的字段,interval指
定區間范圍(可選值有:year、quarter、month、week、day、hour、minute、
second),format指定日期格式化,min_doc_count指定每個區間的最少document(如
果不指定,默認為0,當區間范圍內沒有document時,也會顯示bucket分組),
extended_bounds指定起始時間和結束時間(如果不指定,默認使用字段中日期最小值
所在范圍和最大值所在范圍為起始和結束時間)。
1 ES7.x之前的語法
2 GET /cars/_search
3 {
4 "aggs": {
5 "histogram_by_date" : {
6 "date_histogram": {
7 "field": "sold_date",
8 "interval": "month",
9 "format": "yyyy‐MM‐dd",
10 "min_doc_count": 1,
11 "extended_bounds": {
12 "min": "2021‐01‐01",
13 "max": "2022‐12‐31"
14 }
15 },
16 "aggs": {
17 "sum_by_price": {
18 "sum": {
19 "field": "price"
20 }
21 }
22 }
23 }
24 }
25 }
26 執行后出現
27 #! Deprecation: [interval] on [date_histogram] is deprecated, use [fixed_inter
val] or [calendar_interval] in the future.
28
29 7.X之后
30 GET /cars/_search
31 {
32 "aggs": {
33 "histogram_by_date" : {
34 "date_histogram": {
35 "field": "sold_date",
36 "calendar_interval": "month",
37 "format": "yyyy‐MM‐dd",
38 "min_doc_count": 1,
39 "extended_bounds": {
40 "min": "2021‐01‐01",
41 "max": "2022‐12‐31"
42 }
43 },
44 "aggs": {
45 "sum_by_price": {
46 "sum": {
47 "field": "price"
48 }
49 }
50 }
51 }
52 }
53 }
8、_global bucket
在聚合統計數據的時候,有些時候需要對比部分數據和總體數據。
如:統計某品牌車輛平均價格和所有車輛平均價格。global是用于定義一個全局
bucket,這個bucket會忽略query的條件,檢索所有document進行對應的聚合統計。
GET /cars/_search
2 {
3 "size" : 0,
4 "query": {
5 "match": {
6 "brand": "大眾"
7 }
8 },
9 "aggs": {
10 "volkswagen_of_avg_price": {
11 "avg": {
12 "field": "price"
13 }
14 },
15 "all_avg_price" : {
16 "global": {},
17 "aggs": {
18 "all_of_price": {
19 "avg": {
20 "field": "price"
21 }
22 }
23 }
24 }
25 }
26 }
9、aggs+order
對聚合統計數據進行排序。
如:統計每個品牌的汽車銷量和銷售總額,按照銷售總額的降序排列。
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_of_brand": {
5 "terms": {
6 "field": "brand",
7 "order": {
8 "sum_of_price": "desc"
9 }
10 },
11 "aggs": {
12 "sum_of_price": {
13 "sum": {
14 "field": "price"
15 }
16 }
17 }
18 }
19 }
20 }
如果有多層aggs,執行下鉆聚合的時候,也可以根據最內層聚合數據執行排序。
如:統計每個品牌中每種顏色車輛的銷售總額,并根據銷售總額降序排列。這就像
SQL中的分組排序一樣,只能組內數據排序,而不能跨組實現排序。
1 GET /cars/_search
2 {
3 "aggs": {
4 "group_by_brand": {
5 "terms": {
6 "field": "brand"
7 },
8 "aggs": {
9 "group_by_color": {
10 "terms": {
11 "field": "color",
12 "order": {
13 "sum_of_price": "desc"
14 }
15 },
16 "aggs": {
17 "sum_of_price": {
18 "sum": {
19 "field": "price"
20 }
21 }
22 }
23 }
24 }
25 }
26 }
27 }
10、search+aggs
聚合類似SQL中的group by子句,search類似SQL中的where子句。在ES中是完全可
以將search和aggregations整合起來,執行相對更復雜的搜索統計。
如:統計某品牌車輛每個季度的銷量和銷售額。
1 GET /cars/_search
2 {
3 "query": {
4 "match": {
5 "brand": "大眾"
6 }
7 },
8 "aggs": {
9 "histogram_by_date": {
10 "date_histogram": {
11 "field": "sold_date",
12 "calendar_interval": "quarter",
13 "min_doc_count": 1
14 },
15 "aggs": {
16 "sum_by_price": {
17 "sum": {
18 "field": "price"
19 }
20 }
21 }
22 }
23 }
24 }
11、filter+aggs
在ES中,filter也可以和aggs組合使用,實現相對復雜的過濾聚合分析。
如:統計10萬~50萬之間的車輛的平均價格。
1 GET /cars/_search
2 {
3 "query": {
4 "constant_score": {
5 "filter": {
6 "range": {
7 "price": {
8 "gte": 100000,
9 "lte": 500000
10 }
11 }
12 }
13 }
14 },
15 "aggs": {
16 "avg_by_price": {
17 "avg": {
18 "field": "price"
19 }
20 }
21 }
22 }
12、聚合中使用filter
filter也可以使用在aggs句法中,filter的范圍決定了其過濾的范圍。
如:統計某品牌汽車最近一年的銷售總額。將filter放在aggs內部,代表這個過濾器
只對query搜索得到的結果執行filter過濾。如果filter放在aggs外部,過濾器則會過
濾所有的數據。
12M/M 表示 12 個月。
1y/y 表示 1年。
d 表示天
1 GET /cars/_search
2 {
3 "query": {
4 "match": {
5 "brand": "大眾"
6 }
7 },
8 "aggs": {
9 "count_last_year": {
10 "filter": {
11 "range": {
12 "sold_date": {
13 "gte": "now‐12M"
14 }
15 }
16 },
17 "aggs": {
18 "sum_of_price_last_year": {
19 "sum": {
20 "field": "price"
21 }
22 }
23 }
24 }
25 }
26 }