mongodb-schema-design 是做什么的?
MongoDB 模式设计模式与反模式。适用于设计数据模型、审查模式、从 SQL 迁移,或排查由模式问题引起的性能问题。触发词包括“设计模式”、“嵌入 vs 引用”、“MongoDB 数据模型”、“模式审查”、“无限数组”、“一对多”、“树形结构”、“16MB 限制”、“模式验证”、“JSON Schema”、“时间序列”、“模式迁移”、“多态”、“TTL”、“数据生命周期”、“归档”、“索引爆炸”、“不必要的索引”、“近似模式”、“文档版本控制”。
概述
本技能提供全面指导,帮助您在设计 MongoDB 模式时做出正确决策。涵盖从基础概念(如嵌入与引用)到高级模式(包括多态、时间序列和文档版本控制)的所有内容。
使用场景
- 从 SQL 迁移:将关系型数据模型转换为 MongoDB 文档模型
- 性能排查:诊断并修复由模式问题(如无限数组、文档过大)导致的性能瓶颈
- 模式审查:对现有模式进行审查,识别反模式并提出优化方案
- 生命周期管理:利用 TTL 索引、归档策略管理数据生命周期
常见模式与反模式
| 模式/反模式 | 描述 | 适用场景 |
|---|---|---|
| 嵌入 vs 引用 | 决定将相关数据嵌入文档还是通过引用关联 | 一对少数关系适合嵌入,一对多关系适合引用 |
| 无限数组 | 数组元素无限制增长,导致文档大小超限 | 应避免,改用分桶模式或引用 |
| 树形结构 | 表示层次化数据(如分类、组织架构) | 使用子节点引用、父节点引用或物化路径 |
| 多态模式 | 在同一集合中存储形状不同的文档 | 适用于属性变化较大的场景 |
| 时间序列 | 高效存储和查询随时间变化的数据 | 使用时间桶、降采样等策略 |
| 文档版本控制 | 跟踪文档的历史版本 | 使用单独的历史集合或软删除 |
最佳实践
- 始终使用模式验证:通过 JSON Schema 确保数据完整性
- 避免索引爆炸:仅在查询模式需要的字段上创建索引
- 监控文档大小:使用
Object.bsonsize()检查文档是否接近 16MB 限制 - 合理使用 TTL:对自动过期数据设置 TTL 索引,减少手动清理
- 测试迁移脚本:在生产环境执行前使用真实数据量测试模式变更
代码示例
嵌入文档(适用于一对少关系)
// 用户及其地址(嵌入)
{
_id: ObjectId("user123"),
name: "张三",
addresses: [
{ street: "长安街", city: "北京", type: "home" },
{ street: "浦东大道", city: "上海", type: "work" }
]
}
引用(适用于一对多关系)
// 文章及其评论(引用)
// articles 集合
{
_id: ObjectId("article456"),
title: "MongoDB 入门指南",
comment_ids: [ObjectId("comm1"), ObjectId("comm2")]
}
// comments 集合
{
_id: ObjectId("comm1"),
article_id: ObjectId("article456"),
content: "好文章!",
author: "李四"
}
模式验证(JSON Schema)
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: {
bsonType: "string",
description: "用户名称,必填"
},
email: {
bsonType: "string",
pattern: "^.+@.+$",
description: "合法邮箱地址,必填"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 150
}
}
}
}
})
时间序列数据(使用时间桶)
// 按小时聚合传感器数据
db.sensor_readings.updateOne(
{ sensor_id: "sensor001", hour: ISODate("2023-10-01T00:00:00Z") },
{
$push: { readings: { temp: 25.5, timestamp: new Date() } },
$inc: { count: 1 }
},
{ upsert: true }
)