MongoDB 的聚合框架提供了一种强大的方式来处理数据并生成汇总报告。它允许你对文档执行复杂的分组操作,如计算平均值、总和、最大值、最小值等,并支持多阶段的数据处理。
基本语法
聚合管道由一系列称为“阶段”的操作组成,这些操作通过管道连接起来。每个阶段对数据集进行一次转换。最常用的聚合操作包括 $match
, $group
, $sort
, $project
, $lookup
, $unwind
, $limit
, $skip
等。
聚合管道的基本语法如下:
db.collection.aggregate([
{ $stage1: {} },
{ $stage2: {} },
...
])
常用的聚合阶段
- $match: 过滤文档。
- $group: 按指定字段分组文档。
- $sort: 排序输出文档。
- $project: 修改输出文档的结构。
- $lookup: 执行左外连接。
- $unwind: 将数组字段拆分为多条文档。
- $limit: 限制输出文档的数量。
- $skip: 跳过指定数量的文档。
示例
假设我们有一个名为 orders
的集合,包含用户的订单信息,每个订单文档包含 userId
, orderDate
, totalPrice
等字段。
示例 1: 统计每个用户的订单总数
db.orders.aggregate([
{ $group: { _id: "$userId", totalOrders: { $sum: 1 } } }
])
示例 2: 计算每个用户的订单总价
db.orders.aggregate([
{ $group: { _id: "$userId", totalSpent: { $sum: "$totalPrice" } } }
])
示例 3: 获取每个用户的最新订单
db.orders.aggregate([
{ $sort: { orderDate: -1 } },
{ $group: { _id: "$userId", latestOrder: { $first: "$$ROOT" } } },
{ $replaceRoot: { newRoot: "$latestOrder" } }
])
示例 4: 使用 $lookup 进行联接
假设我们还有另一个集合 users
,包含用户的信息,如 userId
, firstName
, lastName
。我们可以将 orders
集合与 users
集合联接,以便获取每个订单的用户详细信息。
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "userId",
foreignField: "userId",
as: "userDetails"
}},
{ $unwind: "$userDetails" },
{ $project: {
userId: 1,
orderDate: 1,
totalPrice: 1,
user: "$userDetails"
}}
])
使用示例
以下是一个使用 Node.js 和 MongoDB 驱动程序执行聚合查询的示例:
const MongoClient = require('mongodb').MongoClient;
const uri = "your_connection_string_here";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
client.connect(err => {
const collection = client.db("test").collection("orders");
collection.aggregate([
{ $group: { _id: "$userId", totalOrders: { $sum: 1 } } }
]).toArray((err, results) => {
if (err) throw err;
console.log(results);
client.close();
});
});
性能考虑
- 确保对经常出现在
$match
和$sort
阶段中的字段创建索引。 - 使用
$match
尽早过滤数据,以减少后续阶段的数据量。 - 对于大型数据集,考虑使用
$limit
来限制结果集大小。
如果你需要更详细的示例或有其他具体需求,请告诉我!