MongoDB聚合管道:初學者也能看懂的數據分析方法

一、什麼是MongoDB聚合管道?

想象你有一堆散落的數據,比如學生的考試成績、購物訂單信息,現在要分析這些數據:比如統計各科平均分、找出最高分學生、按類別分組統計等。MongoDB的聚合管道就像一條“數據流水線”,你可以把數據依次經過多個“加工站”(稱爲“階段”),每個加工站對數據做不同處理,最後得到你想要的分析結果。

舉個例子:
你有一個“學生成績表”集合(類似Excel表格),裏面記錄了每個學生的姓名、科目、分數。要分析“數學平均分”,你不需要先把所有數據導出到Excel,再手動計算,而是用聚合管道“一步到位”:先篩選出“科目=數學”的學生(篩選階段),再計算這些學生的平均分(分組統計階段)。

二、聚合管道的核心概念

聚合管道由多個“階段” 組成,每個階段是一個“加工站”,數據從第一個階段流到下一個,最終輸出結果。階段的順序很重要,因爲每個階段處理前一個階段的輸出。

核心階段和操作符

階段名(操作符) 作用通俗解釋 類似SQL
$match 篩選數據(類似 find() 查詢) WHERE
$project 只保留需要的字段(或重命名/計算新字段) SELECT
$group 按條件分組,統計數據(如平均分、總數) GROUP BY
$sort 對結果排序 ORDER BY
$limit 限制返回的數據量 LIMIT

三、實戰案例:從簡單到複雜

假設我們有一個名爲 students 的集合,數據結構如下(簡化版):

{
  "_id": 1,
  "name": "張三",
  "class": 1,
  "subject": "數學",
  "score": 85
},
{
  "_id": 2,
  "name": "李四",
  "class": 1,
  "subject": "數學",
  "score": 92
},
{
  "_id": 3,
  "name": "王五",
  "class": 2,
  "subject": "數學",
  "score": 78
}

案例1:篩選+投影(只看數學成績)

需求:找出1班學生的數學成績,只顯示姓名和分數。
代碼實現

db.students.aggregate([
  // 階段1:篩選班級=1且科目=數學的學生
  { $match: { class: 1, subject: "數學" } },
  // 階段2:只保留姓名和分數字段
  { $project: { _id: 0, name: 1, score: 1 } }
])

輸出結果

{ "name": "張三", "score": 85 },
{ "name": "李四", "score": 92 }

解釋
- $match 相當於 SQL 的 WHERE class=1 AND subject="數學",只保留符合條件的文檔。
- $project 中的 _id: 0 表示不顯示默認的 _id 字段,name: 1score: 1 表示顯示這兩個字段。

案例2:分組統計(按科目計算平均分)

需求:按“科目”分組,計算每個科目的平均分數。
代碼實現

db.students.aggregate([
  // 階段1:按科目分組,計算平均分
  { $group: {
      _id: "$subject",       // 分組依據:科目字段
      avgScore: { $avg: "$score" }  // 計算平均分,$avg 是累加器操作符
    }
  },
  // 階段2:按平均分降序排序
  { $sort: { avgScore: -1 } }
])

輸出結果

{ "_id": "數學", "avgScore": 85.0 },
{ "_id": "語文", "avgScore": 76.5 }  // 假設還有語文數據

解釋
- $group_id: "$subject" 表示按“科目”字段分組。
- avgScore 是自定義的統計結果名,$avg: "$score" 表示對每個分組的 score 字段求平均值。
- $sortavgScore 降序排列(-1 表示降序,1 表示升序)。

案例3:多階段組合(統計班級平均分+總人數)

需求:統計每個班級每個科目的平均分和總人數。
代碼實現

db.students.aggregate([
  // 階段1:按班級+科目分組
  { $group: {
      _id: { class: "$class", subject: "$subject" },  // 複合分組:班級+科目
      totalStudents: { $sum: 1 },       // 總人數:每個文檔+1
      avgScore: { $avg: "$score" }       // 平均分
    }
  },
  // 階段2:按班級排序
  { $sort: { "_id.class": 1, "_id.subject": 1 } }
])

輸出結果

{ "_id": { "class": 1, "subject": "數學" }, "totalStudents": 2, "avgScore": 88.5 },
{ "_id": { "class": 2, "subject": "數學" }, "totalStudents": 1, "avgScore": 78.0 }

解釋
- $group_id 可以是一個對象,包含多個字段(班級+科目),實現複合分組。
- $sum: 1 是統計總人數的常用寫法(每個文檔貢獻1個計數)。

四、常用操作符速查表

操作符 作用 示例
$match 篩選文檔 { $match: { score: { $gt: 60 } } }(分數>60)
$project 控制輸出字段 { $project: { name: 1, newScore: { $add: ["$score", 5] } } }
$group 分組並統計 { $group: { _id: "$subject", total: { $sum: "$score" } } }
$sort 排序 { $sort: { score: -1 } }(降序)
$limit 限制數量 { $limit: 10 }(取前10條)
$skip 跳過數據 { $skip: 5 }(跳過前5條)

五、總結

MongoDB聚合管道就像“數據加工廠”,通過多個階段的組合,你可以輕鬆完成複雜的數據分析:
1. 篩選:用 $match 過濾不需要的數據;
2. 投影:用 $project 只保留關鍵信息;
3. 分組:用 $group 按條件統計(平均分、總數等);
4. 排序/限制:用 $sort$limit 優化結果。

從簡單例子開始,逐步嘗試多階段組合,你會發現聚合管道比手動在代碼中處理數據更高效、更靈活!

小建議:多練習不同場景的組合(比如“先篩選再分組”“先排序再限制”),熟悉每個階段的作用,很快就能掌握~

小夜