DAY12 Facet 與 Bucket 分桶統計
之前我們介紹過了 Aggregation pipeline 了,如果不太了解,請往前看 DAY10, DAY11 的文章。
Aggregate 可以經過一堆操作呈現出我們要的結果,那如果我們要的結果是有一種以上的呈現方式怎麼辦?例如一個學校想看本校學測的學生們分析資料,一個想看按分數來分群,一個想看按班級來分群,就得準備兩次查詢語法,再分別記錄下來。
當然不用這麼麻煩,這時候就是 facet
出場的時候了,facet 能夠在一次查詢內執行多個 aggregate 並回傳結果,這樣做的好處就是來源資料只需要查詢一次。兩次可能還無法看出效果,如果是十次二十次呢?輸入的資料只需做一次,就能省掉額外的消耗。
我們先來看看 Facet 的 pattern:
1 | db.artwork.aggregate( [ |
在使用上有些原生的限制:
- aggregate RAM 最多使用 100 MB
- facet out 最多只能 16 MB
知道使用規則後,我們就來準備範例的資料了。
1 | db.facet.insertMany([ |
在今天之前,我們想達到以下兩種統計
按年份統計
有幾部電影以及總成本多少?按評分統計
有幾部電影以及總成本多少?
我們應該是會這樣寫著:
1 | db.facet.aggregate( |
分兩次查也挺好的。謝謝大家!(被打)
使用 facet 一次查詢完也是挺簡單的,語法如下:
1 | db.facet.aggregate([ |
結果如下:
1 | { |
其實我在使用上就是當作兩個 aggregate 在寫,先各別擊破後再組合,這樣也比較好 debug。
中間的 { $match: { publishYear : { $gte: 1 } } }
與 { $match: {} }
是刻意這樣寫的,目的只是表現不需要過濾條件時,就這樣做即可。
$bucket
aggregate 使用利器還有一個分桶的運算子,叫做 bucket
(以及 bucketAuto
),功能是幫你統計的欄位進行各別統計,而分桶的方式以及刻度都能夠自行定義,便於呈現結果。這個東西算是能夠自行訂刻度的 group
,來看看它的 Pattern
1 | { |
- groupBy: 分群的欄位
- boundaries: 就是所有值的上下界,以及中間的刻度。
已上面的範例,出版的年份從1988~2020
,我們上下界線就是[1988, 2020]
,也可以自己定義範圍[1988, 2000, 2010, 2020]
- default: 當分群欄位的值不在上面定義的範圍時,要顯示的名稱,等下看範例就知道
- output: 上面分群後的結果
我們使用出版年來分群,分群為 1988, 2000, 2010, 2020,剩下的就放在名為 others
類別,並在每一份統計數量以及電影名字,馬上來看範例:
1 | film> db.facet.aggregate([ |
這邊要特別注意的是 movie1 與 movie7,他們的出版年是 2020,觸及了設定的 boundary 上限,也就是這個功能的上下界關係是
>=
lower bound<
upper bound