后端工程Technical Deep Dive
MongoDB 实战:文档数据库应用场景
发布时间2026/03/29
分类后端工程
预计阅读8 分钟
作者吴长龙
*
MongoDB 实战:文档数据库应用场景
01.内容
# MongoDB 实战:文档数据库应用场景
MongoDB 是最流行的文档数据库,其灵活的 Schema 非常适合快速迭代的业务场景。本文介绍 MongoDB 的核心概念、进阶操作以及与 PostgreSQL 的选型建议。
02.一、核心概念
1.1 与关系型数据库对比
| 关系型 | MongoDB |
|---|---|
| Database | Database |
| Table | Collection |
| Row | Document |
| Column | Field |
| JOIN | $lookup / 嵌入文档 |
| PRIMARY KEY | _id |
1.2 文档结构
javascript snippetjavascript
// MongoDB 文档(BSON)
{
_id: ObjectId("5f47a1b..."),
name: "张三",
email: "zhangsan@example.com",
profile: {
age: 28,
city: "北京",
tags: ["vip", "developer"]
},
orders: [
{ orderId: 1, amount: 100 },
{ orderId: 2, amount: 200 }
],
createdAt: ISODate("2026-01-01T00:00:00Z"),
status: "active"
}03.二、基本操作
2.1 CRUD
javascript snippetjavascript
const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('mydb');
const users = db.collection('users');
// 插入
await users.insertOne({ name: '张三', email: 'zhangsan@example.com' });
await users.insertMany([
{ name: '李四', email: 'lisi@example.com' },
{ name: '王五', email: 'wangwu@example.com' }
]);
// 查询
await users.find({ status: 'active' }).toArray();
await users.findOne({ _id: new ObjectId("...") });
// 条件查询
await users.find({
age: { $gte: 18, $lte: 35 },
status: 'active',
tags: { $in: ['vip', 'premium'] }
}).sort({ createdAt: -1 }).skip(20).limit(10);
// 更新
await users.updateOne(
{ _id: new ObjectId("...") },
{ $set: { name: '张三新' }, $inc: { age: 1 } }
);
// 删除
await users.deleteOne({ _id: new ObjectId("...") });2.2 聚合管道
javascript snippetjavascript
// 聚合管道:数据处理流水线
const pipeline = [
// 1. 筛选
{ $match: { status: 'active', createdAt: { $gte: new Date('2026-01-01') } } },
// 2. 展开数组
{ $unwind: '$orders' },
// 3. 分组统计
{ $group: {
_id: '$userId',
totalAmount: { $sum: '$orders.amount' },
orderCount: { $sum: 1 }
}},
// 4. 排序
{ $sort: { totalAmount: -1 } },
// 5. 限制
{ $limit: 10 },
// 6. 投影
{ $project: {
userId: '$_id',
totalAmount: 1,
orderCount: 1,
_id: 0
}}
];
const results = await users.aggregate(pipeline).toArray();2.3 索引
javascript snippetjavascript
// 单字段索引
await users.createIndex({ email: 1 }, { unique: true });
// 复合索引(顺序重要)
await users.createIndex({ status: 1, createdAt: -1 });
// 多键索引(数组字段)
await users.createIndex({ tags: 1 });
// 文本索引(搜索)
await posts.createIndex({ title: 'text', content: 'text' });
await posts.find({ $text: { $search: 'MongoDB 教程' } });
// 查看查询计划
await users.find({ status: 'active' }).explain();04.三、进阶模式
3.1 文档嵌入 vs 引用
javascript snippetjavascript
// 嵌入:数据经常一起查询
{
name: "订单1",
items: [
{ productId: 1, name: "商品A", price: 100 },
{ productId: 2, name: "商品B", price: 200 }
]
}
// 引用:数据独立更新、很大
{
orderId: 1,
userId: ObjectId("..."), // 引用
items: [
{ productId: ObjectId("..."), quantity: 1 }
]
}
// 查询时使用 $lookup
const orders = await db.collection('orders').aggregate([
{
$lookup: {
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user'
}
},
{ $unwind: '$user' },
{ $project: { 'user.password': 0 } } // 排除敏感字段
]).toArray();3.2 变更流(Change Stream)
javascript snippetjavascript
// 监听数据变更
const changeStream = db.collection('users').watch();
changeStream.on('change', (change) => {
switch (change.operationType) {
case 'insert':
console.log('新增:', change.fullDocument);
break;
case 'update':
console.log('更新:', change.updateDescription);
break;
case 'delete':
console.log('删除:', change.documentKey);
break;
}
});
// 用于微服务同步、实时推送等场景05.四、事务支持
javascript snippetjavascript
// MongoDB 4.0+ 支持多文档事务
const session = client.startSession();
try {
await session.withTransaction(async () => {
const users = db.collection('users');
const accounts = db.collection('accounts');
// 转账
await accounts.updateOne(
{ userId: fromUserId },
{ $inc: { balance: -amount } },
{ session }
);
await accounts.updateOne(
{ userId: toUserId },
{ $inc: { balance: amount } },
{ session }
);
// 记录日志
await db.collection('transactions').insertOne({
from: fromUserId,
to: toUserId,
amount,
timestamp: new Date()
}, { session });
});
} finally {
await session.endSession();
}06.五、选型建议
5.1 何时选择 MongoDB
| 场景 | 原因 |
|---|---|
| 快速迭代的产品 | Schema 灵活,无需迁移 |
| 日志/分析数据 | 写入量大,结构多样 |
| 用户行为数据 | 嵌套文档,减少 JOIN |
| 内容管理系统 | 文档即文章,天然匹配 |
| 物联网数据 | 时间序列文档 |
5.2 何时选择 PostgreSQL
| 场景 | 原因 |
|---|---|
| 强一致性要求 | ACID 事务 |
| 复杂查询 | SQL 成熟稳定 |
| 财务报表 | 精确数值 |
| 关系复杂 | JOIN 查询 |
| 团队熟悉 | 生态成熟 |
5.3 混合使用
javascript snippetjavascript
// 常见模式:MongoDB + PostgreSQL
// - PostgreSQL: 用户、订单、支付等核心业务
// - MongoDB: 用户行为日志、内容管理、缓存数据
// 或者:同一个应用,不同服务选择不同数据库
// 用户服务 -> PostgreSQL
// 日志服务 -> MongoDB07.总结
| 特性 | MongoDB | PostgreSQL |
|---|---|---|
| Schema | 灵活(无模式) | 固定 |
| JOIN | 有限 | 完整支持 |
| 事务 | 4.0+ 多文档 | 原生 ACID |
| 性能(写入) | 高 | 中 |
| 社区 | 大 | 大 |
建议:如果是新项目且不确定数据模型,用 MongoDB 快速开发;业务稳定后,可考虑迁移到 PostgreSQL 获取更强的查询能力。
---
*后续将介绍容器化与部署实战。*