MongoDB文档模型设计指南
MongoDB作为文档型数据库,其数据模型设计与传统关系型数据库有很大不同。合理的数据模型设计直接影响到查询性能、数据一致性和开发效率。本文将介绍MongoDB文档模型设计的核心原则和最佳实践。
一、嵌入 vs 引用
这是MongoDB数据模型设计中最核心的决策:
// 嵌入文档 - 适合一对一和少量一对多关系
// 优点:一次查询获取所有数据,无需JOIN
{
_id: ObjectId("..."),
name: "张三",
address: {
city: "北京",
street: "中关村大街1号",
zipCode: "100080"
},
contacts: [
{ type: "phone", value: "13800138000" },
{ type: "email", value: "zhangsan@example.com" }
]
}
// 引用文档 - 适合多对多和大量一对多关系
{
_id: ObjectId("..."),
orderNo: "ORD20240101001",
userId: ObjectId("..."), // 引用用户ID
items: [
{ productId: ObjectId("..."), quantity: 2, price: 99.9 }
]
}
二、常见模式设计
// 模式1:属性模式 - 处理动态属性
{
name: "笔记本电脑",
attrs: [
{ k: "品牌", v: "联想" },
{ k: "内存", v: "16GB" },
{ k: "CPU", v: "i7-13700H" }
]
}
// 建立索引
db.products.createIndex({ "attrs.k": 1, "attrs.v": 1 })
// 模式2:桶模式 - 时序数据
{
sensorId: "TEMP_001",
date: ISODate("2024-01-01"),
readings: [
{ time: "00:00", value: 22.5 },
{ time: "01:00", value: 22.3 }
],
min: 20.1,
max: 25.8,
avg: 22.8
}
// 模式3:多态模式
{
_id: ObjectId("..."),
type: "book",
title: "MongoDB权威指南",
author: "Kristina Chodorow",
pages: 432
}
{
_id: ObjectId("..."),
type: "electronics",
name: "无线鼠标",
brand: "罗技",
warranty: 12
}
三、索引优化
// ESR原则:Equal, Sort, Range
// 精确匹配 → 排序 → 范围查询
// 查询:{ status: "active" }.sort({ createdAt: -1 }).limit(20)
// 最佳索引:
db.orders.createIndex({ status: 1, createdAt: -1 })
// 复合索引
db.users.createIndex({ city: 1, age: -1, name: 1 })
// 文本索引
db.articles.createIndex({ title: "text", content: "text" })
db.articles.find({ text: { search: "MongoDB 性能" } })
// TTL索引 - 自动过期
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
// 部分索引 - 减少索引大小
db.orders.createIndex(
{ status: 1, createdAt: -1 },
{ partialFilterExpression: { status: "active" } }
)
四、聚合管道
// 统计每月销售额
db.orders.aggregate([
{ match: { status: "completed", createdAt: { gte: ISODate("2024-01-01") } } },
{ group: {
_id: { dateToString: { format: "%Y-%m", date: "$createdAt" } },
totalSales: { sum: "$amount" },
orderCount: { sum: 1 },
avgOrder: { avg: "$amount" }
}},
{ sort: { _id: 1 } }
])
MongoDB的文档模型给了开发者极大的灵活性,但也带来了更大的设计责任。核心原则是:根据应用的查询模式来设计数据模型,让最频繁的查询最高效。切忌简单地将关系型数据库的表直接搬运为MongoDB的集合。