MongoDB聚合查詢實例:統計分析用戶數據

在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_countavg_agemax_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/),多動手寫代碼驗證結果!

小夜