在MongoDB中,聚合查詢(Aggregation)是一種強大的數據處理工具,它允許我們對集合中的文檔進行多階段的轉換和分析,就像流水線一樣處理數據。比如統計不同地區的用戶數量、計算用戶平均年齡、分析訂單總金額等,這些都可以通過聚合管道輕鬆實現。
準備示例數據¶
爲了方便理解,我們假設一個用戶數據集合users,每個用戶文檔結構如下(簡化版):
{
"_id": ObjectId("..."),
"name": "張三",
"age": 25,
"gender": "男",
"region": "北京",
"orders": [
{ "amount": 100, "date": "2023-01-01" },
{ "amount": 150, "date": "2023-02-15" }
]
}
包含的字段:姓名(name)、年齡(age)、性別(gender)、地區(region)、訂單數組(orders,每個訂單有金額amount和日期date)。
基礎聚合階段介紹¶
MongoDB聚合管道由多個階段(Stage) 組成,每個階段處理數據的一個操作,前一個階段的輸出作爲下一個階段的輸入。常用階段和操作符:
- $match:過濾文檔(類似SQL的WHERE)
- $group:按指定字段分組,配合累加器(如$sum、$avg)統計結果
- $project:只保留需要的字段(類似SQL的SELECT)
- $sort:按指定字段排序(類似SQL的ORDER BY)
- $unwind:展開數組字段(如將orders數組拆分爲多個文檔)
- 累加器操作符:$sum(求和)、$avg(平均值)、$max(最大值)、$min(最小值)
實例1:統計每個性別的用戶數量¶
需求:統計“男”“女”用戶各有多少人。
聚合管道:
db.users.aggregate([
{
$group: {
_id: "$gender", // 按gender字段分組
count: { $sum: 1 } // 每個分組的文檔數+1(即統計數量)
}
},
{
$sort: { count: -1 } // 按數量降序排序
}
])
解釋:
- $group:按gender分組,_id指定分組字段,count是統計結果字段,$sum:1表示每個文檔加1(即每個用戶算1次)。
- $sort:按count降序排列,讓結果更直觀。
輸出示例:
[
{ "_id": "男", "count": 120 },
{ "_id": "女", "count": 80 }
]
實例2:統計各地區用戶的平均年齡¶
需求:計算每個地區用戶的平均年齡(忽略年齡爲null的用戶)。
聚合管道:
db.users.aggregate([
{
$match: { age: { $exists: true } } // 過濾掉age不存在的用戶
},
{
$group: {
_id: "$region", // 按地區分組
avg_age: { $avg: "$age" } // 計算該地區用戶的平均年齡
}
},
{
$project: { // 只保留需要的字段,隱藏_id
region: "$_id",
avg_age: 1,
_id: 0
}
},
{
$sort: { avg_age: -1 } // 按平均年齡降序排列
}
])
解釋:
- $match:用$exists: true過濾掉沒有年齡數據的用戶,避免$avg計算錯誤。
- $group:$avg: "$age"計算分組內的平均年齡(自動忽略null/不存在的字段)。
- $project:將_id重命名爲region,並隱藏原始_id,結果更清晰。
實例3:統計每個用戶的總消費金額¶
需求:用戶可能有多個訂單,需要統計每個用戶的訂單總金額。
聚合管道:
db.users.aggregate([
{
$unwind: "$orders" // 展開orders數組,每個訂單拆分爲獨立文檔
},
{
$group: {
_id: "$_id", // 按用戶ID分組(即每個用戶)
total_amount: { $sum: "$orders.amount" } // 累加每個訂單的金額
}
},
{
$sort: { total_amount: -1 }, // 按總金額降序排列
$limit: 10 // 只取消費最高的前10個用戶
}
])
解釋:
- $unwind: "$orders":將orders數組中的每個元素拆分爲獨立文檔(例如一個用戶有2個訂單,拆分爲2個文檔)。
- $group:按用戶_id分組,累加每個訂單的amount金額。
- $limit: 10:只取前10條結果(可配合$skip實現分頁,如$skip: 20跳過前20條)。
實例4:統計各地區用戶數量、平均年齡、最大年齡¶
需求:同時統計每個地區的用戶數、平均年齡和最大年齡。
聚合管道:
db.users.aggregate([
{
$group: {
_id: "$region",
user_count: { $sum: 1 },
avg_age: { $avg: "$age" },
max_age: { $max: "$age" }
}
},
{
$sort: { user_count: -1 }
}
])
解釋:
- $group中可以同時使用多個累加器:$sum:1統計用戶數,$avg: "$age"計算平均年齡,$max: "$age"取最大年齡。
- 結果會包含每個地區的user_count、avg_age、max_age三個字段。
總結¶
MongoDB聚合查詢通過管道式階段實現靈活的數據處理,適合初學者的核心操作包括:
1. 過濾:用$match縮小數據範圍(類似SQL的WHERE)。
2. 分組統計:用$group+累加器($sum/$avg等)實現統計。
3. 字段處理:用$project隱藏不需要的字段,結果更簡潔。
4. 排序/分頁:用$sort和$limit/$skip控制結果順序和數量。
建議從簡單分組統計開始練習,逐步嘗試複雜場景(如多層嵌套聚合、數組處理等)。遇到問題可參考MongoDB官方文檔的聚合管道語法(https://docs.mongodb.com/manual/reference/operator/aggregation/),多動手寫代碼驗證結果!