第 9 章 MongoDB 進階操作:聚合
9.1 聚合管線概念
在前面第 6 章中,我們學習了基本的 MongoDB 查詢操作(如 find() 方法),這些查詢能滿足簡單的需求。然而,當面臨更為複雜的查詢場景時,多次的 find() 操作可能變得低效且繁瑣。本章將介紹 MongoDB 強大的查詢功能——聚合管線(Aggregation Pipeline),它能有效處理複雜的查詢需求,並簡化數據處理流程。
聚合管線的基本概念
MongoDB 聚合管線是一種數據處理流水線,每個階段執行特定的數據轉換和分析。其核心概念包括:
-
資料流:文檔從集合中流入管線。
-
階段:管線由多個階段組成,每個階段執行特定操作。
-
轉換:每個階段可對數據進行篩選、轉換或分組。
-
結果:管線的最後階段輸出處理完成的結果。
聚合管線的優勢
-
高效性:所有操作均在資料庫內完成,減少了數據傳輸的成本。
-
靈活性:支持多種組合操作,實現複雜的數據轉換。
-
可讀性:階段化的結構使得複雜查詢更容易理解與維護。
聚合管線的應用場景包括計算平均值、統計總和、分組數據等,能在一次查詢中完成多種操作。
簡單查詢與複雜查詢的使用情境
假設我們有一個包含台灣各分區人口資料的集合 people,其中每筆文檔的字段包括 _id、city(城市)、district(分區)、sex(性別)。
範例數據:
{
"_id": "A123456789", "city": "台北市", "district": "信義", "sex": "男"
},
{
"_id": "A123456790", "city": "台北市", "district": "松山", "sex": "女"
}
簡單查詢:一次查詢即可獲得結果
-
計算總人數:
db.people.countDocuments(); -
查詢台北市的人口數:
db.people.countDocuments({ city: "台北市" }); -
查詢台北市男性的人口數:
db.people.countDocuments({ city: "台北市", sex: "男" });
複雜查詢:需要多次查詢
查詢台北市信義區男性與松山區女性的總人數:
-
信義區男性人數:
db.people.countDocuments({ city: "台北市", district: "信義", sex: "男" }); -
松山區女性人數:
db.people.countDocuments({ city: "台北市", district: "松山", sex: "女" });
將結果相加得出答案。
9.1.3 聚合管線的操作
優點:
-
相比傳輸所有原始數據,只傳輸統計結果,大幅節省資源。
-
自動識別分區數量,減少查詢次數。
缺點:
-
無法取得原始數據。
聚合操作的步驟
-
定義問題:例如,統計台灣每個城市分區的男性與女性人數。
-
聚合過程:
-
篩選:過濾出符合條件的文檔。
-
分組:根據分區字段進行分組。
-
計算:統計每組中的男性與女性數量。
-
輸出:將結果返回給用戶。
-
聚合查詢示例:
// 聚合查詢示例
db.people.aggregate([
{ $group: { _id: "$district", male: { $sum: { $cond: [ { $eq: ["$sex", "男"] }, 1, 0 ] } }, female: { $sum: { $cond: [ { $eq: ["$sex", "女"] }, 1, 0 ] } } } }
]);
9.2 聚合運算子
MongoDB 提供超過 30 種的聚合運算子,用於支持豐富的數據處理操作。以下是常見運算子:
| 運算子 | 說明 |
|---|---|
$match |
篩選符合條件的文檔。 |
$group |
根據指定字段分組並進行統計。 |
$project |
映射輸出字段。 |
$limit |
限制返回的文檔數量。 |
$sort |
對結果進行排序。 |
範例:計算每個分區的消費者平均年齡
db.customers.aggregate([
{ $match: { city: "台北市" } },
{ $group: { _id: "$district", avgAge: { $avg: "$age" }, totalCount: { $sum: 1 } } }
]);
9.3 使用範例
範例 1:計算台北市消費者數量與平均年齡
-
匯入資料:
db.customers.insertMany([ { "city": "台北市", "district": "信義", "age": 25 }, { "city": "台北市", "district": "松山", "age": 30 } ]); -
聚合查詢:
db.customers.aggregate([ { $match: { city: "台北市" } }, { $group: { _id: "$district", avgAge: { $avg: "$age" }, totalCount: { $sum: 1 } } } ]);結果:每個分區的消費者平均年齡和總人數。
範例 2:全台灣 107 年出生、死亡、結婚、離婚數據統計
-
匯入資料:匯入政府開放平台的戶籍資料。
-
聚合查詢:
db.people.aggregate([ { $group: { _id: null, totalBirth: { $sum: "$birth_total" }, totalDeath: { $sum: "$death_total" }, totalMarry: { $sum: "$marry_pair" }, totalDivorce: { $sum: "$divorce_pair" } } } ]);結果:返回全台灣的統計數據。
9.4 實戰演練:資料統計系統
此範例使用 C# 搭配 MongoDB Driver 實現數據統計系統,並通過控制台操作執行兩個功能:
-
計算台北市各分區消費者數量與平均年齡。
-
計算 107 年全台灣的出生、死亡、結婚與離婚統計數據。
主要步驟
-
安裝 MongoDB Driver:
Install-Package MongoDB.Driver -Version 2.26.0 -
定義數據結構:
-
CustomersDocument.cs -
`PeopleDocument.cs
-
ChatGPT 說:
請先 登入 以發表留言。