在MongoDB中,使用 $group 阶段可以对文档进行分组和聚合。类似于SQL中的 GROUP BY 子句,$group 允许你根据某些字段对文档进行分组,并对每个组执行聚合操作(如求和、平均值、计数等)。
使用 $group 阶段的基本结构
{
$group: {
_id: <expression>, // 分组条件
<field1>: { <accumulator1>: <expression1> }, // 聚合字段
<field2>: { <accumulator2>: <expression2> },
// 其他聚合字段
}
}
_id是必须的,定义了分组的条件。- 聚合字段使用聚合操作符(如
$sum,$avg,$max,$min等)进行计算。
代码示例
以下是使用Node.js进行分组和聚合操作的详细示例。首先确保安装了MongoDB的Node.js驱动:
npm install mongodb
插入示例数据
const { MongoClient } = require('mongodb');
async function insertData() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri, { useUnifiedTopology: true });
try {
await client.connect();
const db = client.db('myDatabase');
const collection = db.collection('orders');
await collection.deleteMany({}); // 清空集合
await collection.insertMany([
{ customerId: 1, amount: 100, status: "shipped" },
{ customerId: 1, amount: 200, status: "pending" },
{ customerId: 2, amount: 150, status: "shipped" },
{ customerId: 2, amount: 50, status: "pending" },
{ customerId: 3, amount: 250, status: "shipped" }
]);
console.log("Data inserted");
} finally {
await client.close();
}
}
insertData().catch(console.error);
使用 $group 进行聚合
async function aggregateData() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri, { useUnifiedTopology: true });
try {
await client.connect();
const db = client.db('myDatabase');
const collection = db.collection('orders');
// 使用 $group 进行聚合,按照 customerId 分组并计算每个客户的订单总金额
console.log("\n$group stage (sum of amount by customerId):");
let result = await collection.aggregate([
{
$group: {
_id: "$customerId", // 按 customerId 分组
totalAmount: { $sum: "$amount" } // 计算每个组的 amount 总和
}
}
]).toArray();
console.log(result);
// 使用 $group 进行聚合,按照 status 分组并计算每个状态的订单数量和平均金额
console.log("\n$group stage (count and avg amount by status):");
result = await collection.aggregate([
{
$group: {
_id: "$status", // 按 status 分组
count: { $sum: 1 }, // 计数每个组的文档数量
avgAmount: { $avg: "$amount" } // 计算每个组的 amount 平均值
}
}
]).toArray();
console.log(result);
} finally {
await client.close();
}
}
aggregateData().catch(console.error);
在这个示例中,我们演示了如何使用 $group 阶段进行聚合操作:
- 按照
customerId分组并计算每个客户的订单总金额。 - 按照
status分组并计算每个状态的订单数量和平均金额。
运行这个脚本后,你会得到如下结果(示例输出):
// sum of amount by customerId 结果
$group stage (sum of amount by customerId):
[
{ _id: 1, totalAmount: 300 },
{ _id: 2, totalAmount: 200 },
{ _id: 3, totalAmount: 250 }
]
// count and avg amount by status 结果
$group stage (count and avg amount by status):
[
{ _id: 'shipped', count: 3, avgAmount: 166.66666666666666 },
{ _id: 'pending', count: 2, avgAmount: 125 }
]
其他语言示例
类似的聚合操作也可以在其他编程语言中实现,如Python。以下是Python的示例代码:
安装PyMongo
在终端中运行以下命令来安装PyMongo:
pip install pymongo
使用Python进行聚合
from pymongo import MongoClient
def main():
client = MongoClient('mongodb://localhost:27017/')
db = client['myDatabase']
collection = db['orders']
# 使用 $group 进行聚合,按照 customerId 分组并计算每个客户的订单总金额
print("\n$group stage (sum of amount by customerId):")
pipeline = [
{
'$group': {
'_id': "$customerId", # 按 customerId 分组
'totalAmount': { '$sum': "$amount" } # 计算每个组的 amount 总和
}
}
]
result = list(collection.aggregate(pipeline))
for doc in result:
print(doc)
# 使用 $group 进行聚合,按照 status 分组并计算每个状态的订单数量和平均金额
print("\n$group stage (count and avg amount by status):")
pipeline = [
{
'$group': {
'_id': "$status", # 按 status 分组
'count': { '$sum': 1 }, # 计数每个组的文档数量
'avgAmount': { '$avg': "$amount" } # 计算每个组的 amount 平均值
}
}
]
result = list(collection.aggregate(pipeline))
for doc in result:
print(doc)
if __name__ == '__main__':
main()
运行这个脚本后,你会得到类似的结果。通过这些示例,你可以了解到如何在不同编程语言中使用MongoDB的聚合管道进行分组和聚合操作,并根据各种条件进行数据聚合。
$group 示例进一步深入:
1. 计算总和
{
$group: {
_id: "$customerId", // 按 customerId 分组
totalAmount: { $sum: "$amount" } // 计算每个组的 amount 总和
}
}
2. 计算平均值
{
$group: {
_id: "$status", // 按 status 分组
avgAmount: { $avg: "$amount" } // 计算每个组的 amount 平均值
}
}
3. 计数文档
{
$group: {
_id: "$status", // 按 status 分组
count: { $sum: 1 } // 计数每个组的文档数量
}
}
4. 计算最大值和最小值
{
$group: {
_id: "$customerId", // 按 customerId 分组
maxAmount: { $max: "$amount" }, // 计算每个组的 amount 最大值
minAmount: { $min: "$amount" } // 计算每个组的 amount 最小值
}
}
通过这些示例,你可以了解到如何在不同编程语言中使用MongoDB的聚合管道进行分组和聚合操作,并根据各种条件进行数据聚合。