今天要來介紹aggregate比較進階的用法$bucket
,這個操作符它的用法很類似$group
,都是可以將資料透過特定欄位進行分組。
不同的地方在於$group
會把欄位相同值的資料當成一組,但是$bucket
可以指定特定範圍值的資料為一組。
假設我們現在有學生的成績資料
{ id: 1, name: "小美", math: 20 },
{ id: 2, name: "小王", math: 86 },
{ id: 3, name: "小明", math: 98 },
{ id: 4, name: "小帥", math: 56 },
{ id: 5, name: "小真", math: 12 },
{ id: 6, name: "大明", math: "缺考" }
老師想要按照數學成績幫學生分組,並且知道每一組的學生有幾人、名字是誰,我們可以用以下指令,將學生分成3組,1~40分、40~70分、70~100分。
student.aggregate([
{
$bucket: {
groupBy: "$math", // 分組的欄位
boundaries: [1, 40, 70, 101], // 分組的區間範圍
default: "other", // 如果沒有在上面的範圍內,則會在other這一組
output: {
// 決定分組後,要回傳的欄位(每一組都會這樣計算)
"count": { $sum: 1 },
"student": {
$push: {
"student": "$name"
}
}
}
}
}
]);
其中boundaries可以決定分組的區間,按照[1, 40, 70, 101]的寫法,會是分成1≤math<40
、40≤math<70
、70≤math<101
這三組,為了將100分的學生也包含在內,所以最後一個才寫101。
另外default可以讓數學不在1~100分這個範圍內的資料,或原本資料本身缺少math這個欄位,都會被歸類在other這一組。
若是使用boundaries: [0, 40, 70, 101]
這種分法,原本資料本身缺少math這個欄位,會被歸類在0~40分這一組,應該是因為mongodb在判斷上,認為0、null、false都是falsy value的一種。
最後回傳的資料會是
{ _id: 1, count: 2, student: [{ name: "小美" }, { name: "小真" }] },
{ _id: 40, count: 1, student: [{ name: "小帥" }] },
{ _id: 70, count: 2, student: [{ name: "小王" }, { name: "小明" }] },
{ _id: "other", count: 1, student: [{ name: "大明" }] }
ps.分組後的_id
值會是分組值得下限值當id。
本篇文章同步放在我的部落格,大家有空可以進來逛逛