MongoDB的聚合管道就像一條數據處理的流水線,我們可以把數據依次通過不同的“工序”(聚合操作符)進行篩選、統計和轉換,最終得到想要的結果。今天我們來學習聚合管道中最常用的兩個操作符:$match和$group,幫你快速上手MongoDB的聚合分析。
一、MongoDB聚合管道基礎¶
聚合管道由多個階段組成,每個階段對應一個操作符(如$match、$group),數據從左到右依次經過每個階段處理。我們用一個示例集合來理解,假設我們有一個學生成績集合students,文檔結構如下:
{ "_id": 1, "name": "張三", "subject": "數學", "score": 90, "class": "一班" }
{ "_id": 2, "name": "李四", "subject": "語文", "score": 85, "class": "一班" }
{ "_id": 3, "name": "王五", "subject": "數學", "score": 78, "class": "二班" }
{ "_id": 4, "name": "趙六", "subject": "語文", "score": 92, "class": "二班" }
{ "_id": 5, "name": "錢七", "subject": "數學", "score": 88, "class": "一班" }
二、$match:篩選數據的“過濾器”¶
$match就像SQL中的WHERE子句,用來篩選出符合條件的文檔,只把滿足條件的文檔傳遞給下一個階段,避免後續處理無效數據。
語法¶
{ $match: { <查詢條件> } }
<查詢條件>與find()方法的條件一致,支持等於、大於、小於、包含等操作符,例如:
- 等於:{ class: "一班" }(篩選班級爲“一班”的文檔)
- 大於:{ score: { $gt: 80 } }(篩選分數大於80的文檔)
- 包含:{ subject: { $in: ["數學", "語文"] } }(篩選科目爲數學或語文的文檔)
示例:篩選“一班”的學生成績¶
db.students.aggregate([
{ $match: { class: "一班" } } // 只保留class爲“一班”的文檔
])
執行後會返回所有class爲“一班”的3條文檔:
{ "_id": 1, "name": "張三", "subject": "數學", "score": 90, "class": "一班" }
{ "_id": 2, "name": "李四", "subject": "語文", "score": 85, "class": "一班" }
{ "_id": 5, "name": "錢七", "subject": "數學", "score": 88, "class": "一班" }
三、$group:分組統計的“計算器”¶
篩選出數據後,$group會按指定字段分組,並對每個組內的數據進行統計(如計數、求和、求平均等)。
語法¶
{ $group: { _id: <分組鍵>, <自定義字段>: { <累加器操作符>: <字段名> }, ... } }
_id:分組鍵,用來指定分組的依據(如按class或subject分組)。若設爲null,則整個集合作爲一個組。- 自定義字段:如
student_count、avg_score,用來存儲統計結果。 - 累加器操作符:對每個組內的字段進行計算,常用的有:
$sum:求和(如$sum: "$score"計算總分)$avg:求平均值(如$avg: "$score"計算平均分)$count:計數(等價於$sum: 1,統計文檔數量)$max/$min:取最大值/最小值
示例1:按班級分組統計學生數量¶
db.students.aggregate([
{ $group: { _id: "$class", student_count: { $sum: 1 } } }
// 按class分組,每個組計數1(統計學生數量)
])
結果:
{ "_id": "一班", "student_count": 3 },
{ "_id": "二班", "student_count": 2 }
示例2:按科目分組計算總分數¶
db.students.aggregate([
{ $group: { _id: "$subject", total_score: { $sum: "$score" } } }
// 按subject分組,計算每個科目的總分
])
結果:
{ "_id": "數學", "total_score": 90 + 78 + 88 = 256 },
{ "_id": "語文", "total_score": 85 + 92 = 177 }
示例3:按班級分組計算平均分數¶
db.students.aggregate([
{ $group: { _id: "$class", avg_score: { $avg: "$score" } } }
// 按class分組,計算每個班級的平均分
])
結果:
{ "_id": "一班", "avg_score": (90 + 85 + 88)/3 ≈ 87.67 },
{ "_id": "二班", "avg_score": (78 + 92)/2 = 85 }
四、$match和$group組合使用¶
實際分析中,我們常先篩選再分組。例如:統計“數學”科目中每個班級的平均分數。
步驟:¶
- 第一步:用
$match篩選出subject爲“數學”的文檔; - 第二步:用
$group按class分組,計算平均分數。
db.students.aggregate([
{ $match: { subject: "數學" } }, // 篩選數學科目的學生
{ $group: { _id: "$class", avg_math_score: { $avg: "$score" } } } // 按班級分組算平均分
])
結果:
{ "_id": "一班", "avg_math_score": (90 + 88)/2 = 89 },
{ "_id": "二班", "avg_math_score": 78 }
總結¶
$match:像“過濾器”,先篩選數據,減少後續處理量。$group:像“計算器”,按分組鍵分組後,用累加器操作符統計每個組的數據。- 兩者組合是聚合分析的核心模式:先過濾再分組統計。
通過這兩個操作符,你已經能完成基礎的統計分析。後續可學習$project(投影,只保留需要字段)、$sort(排序)等操作符,進一步擴展數據分析能力!