前言
MongoDB 是一个文档型 NoSQL 数据库,灵活的模式设计和强大的查询能力使其在处理非结构化数据时表现优异。本文介绍 MongoDB 的核心概念、优化策略和实际应用。
一、MongoDB 基础概念
1.1 数据模型
- 数据库(Database):最高层级,包含多个集合
- 集合(Collection):相当于关系数据库的表
- 文档(Document):JSON 格式的数据,相当于表的行
- 字段(Field):文档中的键值对,相当于列
1.2 BSON 格式
MongoDB 使用 BSON(Binary JSON)格式存储数据,支持更丰富的数据类型:String、Number、Boolean、Date、Array、Object 等。
二、CRUD 操作
2.1 创建(Insert)
// 单条插入
db.users.insertOne({
name: "Alice",
age: 28,
email: "alice@example.com",
createdAt: new Date()
})
// 批量插入
db.users.insertMany([
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 30 }
])
2.2 查询(Query)
// 基本查询
db.users.find({ age: { $gt: 25 } })
// 数组操作
db.users.find({ tags: { $in: ["python", "java"] } })
// 嵌套对象查询
db.users.find({ "address.city": "Beijing" })
// 聚合管道
db.users.aggregate([
{ $match: { age: { $gt: 25 } } },
{ $group: { _id: "$city", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
2.3 更新(Update)
// 更新单条
db.users.updateOne(
{ _id: ObjectId("...") },
{ $set: { age: 29 } }
)
// 更新多条
db.users.updateMany(
{ status: "inactive" },
{ $set: { status: "active" }, $inc: { loginCount: 1 } }
)
2.4 删除(Delete)
// 删除单条
db.users.deleteOne({ _id: ObjectId("...") })
// 删除多条
db.users.deleteMany({ age: { $lt: 18 } })
三、索引与性能优化
3.1 创建索引
// 创建单字段索引
db.users.createIndex({ email: 1 })
// 创建复合索引
db.orders.createIndex({ userId: 1, createdAt: -1 })
// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// 删除索引
db.users.dropIndex({ email: 1 })
3.2 查询优化
使用 explain() 分析查询执行计划,检查是否使用了索引。
db.users.find({ email: "alice@example.com" }).explain("executionStats")
四、数据设计模式
4.1 嵌入式模式
将相关数据嵌入到单个文档中。优点:查询快速;缺点:可能导致文档过大。
{
_id: 1,
name: "Alice",
address: {
street: "123 Main St",
city: "Beijing",
country: "China"
},
contacts: [
{ type: "email", value: "alice@example.com" },
{ type: "phone", value: "138xxxxxxxx" }
]
}
4.2 引用模式
在文档中存储其他文档的引用。类似关系数据库的外键。
// users 集合
{ _id: 1, name: "Alice" }
// orders 集合
{ _id: 100, userId: 1, amount: 999 }
五、复制与分片
5.1 副本集
一个副本集由多个 MongoDB 实例组成,包括主节点和从节点。主节点接收写入,自动复制到从节点。
5.2 分片
将数据分散到多个服务器,支持水平扩展。根据 shard key 将数据分配到不同的分片。
六、事务支持
MongoDB 4.0 开始支持事务。多文档事务保证 ACID 属性。
session = db.getMongo().startSession()
session.startTransaction()
try {
db.users.updateOne({ _id: 1 }, { $inc: { balance: -100 } })
db.accounts.updateOne({ _id: 2 }, { $inc: { balance: 100 } })
session.commitTransaction()
} catch (e) {
session.abortTransaction()
}
七、最佳实践
- 合理设计文档结构,平衡嵌入和引用
- 为频繁查询的字段创建索引
- 监控慢查询日志,及时优化
- 使用 TTL 索引自动删除过期数据
- 在生产环境使用副本集或分片保证高可用
总结
MongoDB 的灵活性和强大的查询能力,使其成为处理半结构化数据的优秀选择。掌握正确的数据设计模式和优化技巧,能够构建高效的 NoSQL 应用。