关系建模
约 518 字大约 2 分钟
布欧-Lewyon
2026-05-15
首页 › MongoDB › 数据建模(在新窗口打开) › 关系建模
一对一
用户和用户扩展信息:
// 方式一:内嵌(推荐)
{
_id: 1,
name: "Alice",
profile: { avatar: "url", bio: "developer", phone: "138xxx" }
}
// 方式二:引用(数据特别大或更新频繁时)
// users: { _id: 1, name: "Alice" }
// profiles: { _id: 1, userId: 1, avatar: "...", bio: "..." }一对多
博客和评论:
// 方式一:子引用(推荐)
// articles
{ _id: 1, title: "MongoDB 建模", content: "..." }
// comments
{ _id: 100, articleId: 1, text: "好文", author: "Bob" }
{ _id: 101, articleId: 1, text: "赞", author: "Charlie" }
// 查询文章及其评论
db.articles.aggregate([
{ $match: { _id: 1 } },
{ $lookup: {
from: "comments",
localField: "_id",
foreignField: "articleId",
as: "comments"
}}
])// 方式二:父引用(小一对多,数据量有限)
{ _id: 1, name: "Department A", employees: ["uid1", "uid2", "uid3"] }// 方式三:Bucket 模式(按时间分桶)
// 将 1 小时的日志聚合到一个文档
{
deviceId: "sensor01",
hour: ISODate("2026-05-15T10:00:00Z"),
readings: [
{ timestamp: ISODate("2026-05-15T10:00:00Z"), value: 25 },
{ timestamp: ISODate("2026-05-15T10:01:00Z"), value: 26 }
]
}多对多
学生和课程:
// 两边存 ID 数组
// students
{ _id: 1, name: "Alice", courseIds: [101, 102, 103] }
// courses
{ _id: 101, name: "Math", studentIds: [1, 2, 3] }
// 或者用中间集合(适用场景:关联带额外信息)
// enrollments
{ _id: 1, studentId: 1, courseId: 101, enrolledAt: ISODate("2026-01-01"), score: 95 }树形结构
// 方式一:父引用(适合查询父节点)
{
_id: 4,
name: "Technical Manager",
parentId: 2
}
// 方式二:子引用(适合查询子节点)
{
_id: 2,
name: "CTO",
children: [4, 5]
}
// 方式三:祖先数组(适合查询所有祖先或所有后代)
{
_id: 6,
name: "Frontend Dev",
ancestors: [1, 2, 4] // 所有上级的 _id
}小结
- 一对一:内嵌(推荐)或引用(独立更新频繁时)。
- 一对多:子引用(子表存父 ID)是标准方案;Bucket 模式适合时序数据。
- 多对多:两边数组引用,或使用中间集合。
- 树形:父引用、子引用、祖先数组各有取舍。
- 选择依据:查询模式、数据增长方式、更新频率。
