MongoDB 模式设计模式与反模式。用于设计数据模型、审查模式、从 SQL 迁移,或排查由模式问题引起的性能问题。触发词:“设计模式”、“嵌入 vs 引用”、“MongoDB 数据模型”、“模式审查”、“无界数组”、“一对多”、“树结构”、“16MB 限制”、“模式验证”、“JSON Schema”、“时间序列”、“模式迁移”、“多态”、“TTL”、“数据生命周期”、“归档”、“索引爆炸”、“不必要索引”、“近似模式”、“文档版本控制”。
MongoDB 模式设计
由 MongoDB 维护的数据建模模式与反模式。糟糕的模式是大多数 MongoDB 性能和成本问题的根源——查询和索引无法修复根本错误的模型。
何时应用
在以下情况下参考这些指南:
- 从头设计新的 MongoDB 模式
- 从 SQL/关系型数据库迁移到 MongoDB
- 审查现有数据模型以排查性能问题
- 排查慢查询或文档大小增长问题
- 决定嵌入还是引用
- 建模关系(一对一、一对多、多对多)
- 实现树形/层次结构
- 看到 Atlas 模式建议或性能顾问警告
- 达到 16MB 文档限制
- 为现有集合添加模式验证
快速参考
1. 模式反模式 - 3 条规则
- antipattern-unnecessary-collections - 将同质数据拆分为多个集合通常是反模式;请参考本文档验证是否属于这种情况。
- antipattern-excessive-lookups - 当遇到过度规范化的集合相互引用,或频繁且可能缓慢的 $lookup 操作时,请参考本文档验证是否存在问题以及如何修复。
- antipattern-unnecessary-indexes - 当索引重叠或未被查询使用时,请参考本文档识别并移除不必要的索引,这些索引只会增加开销而无益处。
2. 模式基础 - 4 条规则
- fundamental-embed-vs-reference - 参考本文档了解不同类型关系(1:1、1:few、1:many、many:many、树形/层次数据)的建模方法,以及如何根据访问模式决定嵌入还是引用。
- fundamental-document-model - 文档模型基础。从 SQL 或其他规范化数据迁移到 MongoDB 等文档数据库时参考本文档。
- fundamental-schema-validation - 创建新集合或为现有集合添加验证时参考本文档,例如响应发现不一致的文档结构或数据质量问题。
- fundamental-document-size - 当文档达到 16MB 硬限制,或由于文档过大导致访问速度低于预期时参考本文档。
3. 设计模式 - 11 条规则
- pattern-approximation - 对高频计数器使用近似值
- pattern-archive - 将历史数据移至独立/冷存储以提高性能
- pattern-attribute - 将许多可选字段折叠为键值属性
- pattern-bucket - 将时间序列或 IoT 数据分组到桶中
- pattern-computed - 预计算昂贵的聚合
- pattern-document-versioning - 跟踪文档变更以支持历史查询和审计追踪
- pattern-extended-reference - 缓存来自相关实体的频繁访问数据
- pattern-outlier - 处理集合中少数文档远大于其余文档的情况,防止异常值主导内存和索引成本
- pattern-polymorphic - 在同一集合中存储不同类型的实体,通常当它们是同一基础实体的不同类型时(例如不同类型的用户或产品)
- pattern-schema-versioning - 模式演化、防止漂移和安全在线迁移。当遇到不一致的文档结构或计划进行无法原子应用的模式更改时参考。
- pattern-time-series-collections - 对高频时间序列数据使用原生时间序列集合
访问模式分析
不要在没有理解更广泛上下文的情况下立即推荐模式或模式更改。与用户一起分析访问模式,以识别痛点和优化机会。
工作流程
步骤 1:评估环境
询问用户:
- 这是新设计,还是已有生产数据库需要分析现有访问模式?
- 如果有生产数据,是否在 Atlas 上?如果是,什么层级?(M0/M2/M5 还是 M10+)
步骤 2:确定工作负载类型
工作负载是读密集型、写密集型还是均衡?这将影响哪些诊断源最相关。
询问用户:
- 这些集合的主要工作负载是什么——读密集型(分析、报告、搜索)、写密集型(日志记录、IoT 数据摄入、频繁更新)还是均衡?
通过 db.serverStatus().opcounters 验证。
步骤 3:与用户合作选择最佳源
推荐适合其情况的最佳源,并解释权衡。对于模式设计决策,我们通常需要结合多个源以获得完整图景。
步骤 4:进行分析
仅在源选择后,获取数据或引导用户进行分析。
源
- 查询统计 - 返回记录的查询的运行时统计信息,显示查询形状和频率。限制:目前仅捕获读操作(需结合其他源了解写模式)。需要 Atlas M10+ 层级。
- Atlas 慢查询日志 - 审查慢查询(实际查询,而非形状)以识别性能瓶颈。捕获所有读写操作。需要 Atlas M10+ 层级。
- 代码库 - 检查应用程序代码中的实际查询以了解访问模式,尤其适用于新应用程序或工作负载变化时。可与查询统计结合使用以获得更完整的图景。
- 自然语言输入 - 请用户用自然语言描述其典型查询和访问模式。可作为唯一源使用,也可补充和验证其他源——用户可能拥有数据或代码库中未反映的上下文知识。
结合查询统计和慢查询日志:
同时使用两者进行全面分析:
- 查询统计 → 识别频繁访问模式(哪些查询运行最频繁)
- 慢查询日志 → 识别性能瓶颈(哪些查询慢)
- 将模式优化重点放在既频繁又慢的查询上(影响最大)
关键原则
“一起访问的数据应存储在一起。”
这是 MongoDB 的核心理念。嵌入相关数据消除了连接、减少了往返次数并支持原子更新。仅在必要时才引用。
实现这一理念的核心方式是 MongoDB 提供灵活的模式。这意味着不同文档可以有不同的字段,甚至不同的结构。这允许你以最适合访问模式的方式建模数据,而不受僵化模式的约束。例如,如果不同文档有不同的字段集,只要满足应用程序需求,这完全没问题。你还可以使用模式验证来强制执行某些规则,同时保持灵活性。
关键原则的另一个含义是,预期的读写工作负载信息与模式设计高度相关。如果来自不同实体的信息经常被一起查询或更新,那么优先将这些数据共置于同一文档中可以带来显著的性能优势。另一方面,如果某些信息很少被一起访问,则可能有必要分开存储以避免加载不必要的数据。
模式基础总结
- 嵌入 vs 引用:根据访问模式选择嵌入或引用:当数据始终一起访问时嵌入(1:1、1:few、有界数组、需要原子更新);当数据独立访问、关系为多对多或数组可能无界增长时引用。
- 一起访问的数据存储在一起:MongoDB 的核心原则:围绕查询而非实体设计模式。嵌入相关数据以消除跨集合连接并减少往返次数。识别你的 API 端点/页面,列出每个端点返回的数据,然后塑造文档以匹配这些查询。
- 拥抱文档模型:不要将 SQL 表 1:1 重建为 MongoDB 集合。相反,将连接的表反规范化为丰富的文档,以实现单次查询读取和原子更新。从 SQL 迁移时,识别总是连接在一起的表,并将它们合并为单个文档。
- 模式验证:使用 MongoDB 内置的
$jsonSchema验证器在数据库级别捕获无效数据(类型检查、必填字段、枚举约束、数组大小限制)。对现有集合从validationLevel: "moderate"和validationAction: "warn"开始,然后收紧为strict/error。 - 16MB 文档限制:MongoDB 文档不能超过 16MB——这是硬限制,而非指南。常见原因:无界数组、大型嵌入式二进制文件、深度嵌套对象。通过将无界数据移至独立集合并使用
$bsonSize监控文档大小来缓解。
嵌入/引用决策框架
| 关系 | 基数 | 访问模式 | 推荐 |
|---|---|---|---|
| 一对一 | 1:1 | 始终一起 | 嵌入 |
| 一对少数 | 1:N (N < 100) | 通常一起 | 嵌入数组 |
| 一对多 | 1:N (N > 100) | 经常分开 | 引用 |
| 多对多 | M:N | 变化 | 双向引用 |
这是一个粗略指南,是否嵌入或引用取决于你的具体访问模式、数据大小和读写频率。始终根据实际工作负载进行验证。
如何使用
上面列出的每个参考文件都包含详细解释和代码示例。使用快速参考中的描述来识别哪些文件与当前任务相关。
每个参考文件包含:
- 为何重要的简要说明
- 错误代码示例及解释
- 正确代码示例及解释
- “何时不使用”的例外情况
- 性能影响和指标
- 验证诊断
这些规则如何工作
MongoDB MCP 集成
对于自动验证,连接 MongoDB MCP Server。
如果 MCP 服务器正在运行并已连接,我可以自动运行验证命令来检查你的实际模式、文档大小、数组长度、索引使用情况、慢查询日志等。这使我能够基于你的真实数据(而不仅仅是代码模式)提供量身定制的建议。
⚠️ 安全:使用 --readOnly 以确保安全。仅在需要写操作时移除。
连接后,我可以自动:
- 通过
mcp__mongodb__collection-schema推断模式 - 通过
mcp__mongodb__aggregate测量文档/数组大小 - 通过
mcp__mongodb__db-stats检查集合统计信息
⚠️ 操作策略
未经你明确批准,我绝不会执行写操作。
在通过 MCP 执行任何写或破坏性操作之前,我将:(1) 总结确切操作(集合、索引/验证器、预计影响的文档数),以及 (2) 请求明确确认(是/否)。我不会在部分或模糊批准的情况下继续。
| 操作类型 | MCP 工具 | 操作 |
|---|---|---|
| 读取(安全) | find, aggregate, collection-schema, db-stats, count |
我可自动运行以验证 |
| 写入(需批准) | update-many, insert-many, create-collection |
我将显示命令并等待你的“是” |
| 破坏性(需批准) | delete-many, drop-collection, drop-database |
我将警告你并要求明确确认 |
当我推荐模式更改或数据修改时:
- 我会解释什么以及为什么
- 我会向你展示确切命令
- 我会等待你的批准再执行
- 如果你说“继续”或“是”,我才会运行
你的数据库,你的决定。 我在此提供建议,而非单方面行动。
合作方式
如果你对某个建议不确定:
- 运行我提供的验证命令
- 将输出分享给我
- 我会根据你的实际数据调整建议
我们是一个团队——让我们一起把事情做好。






