MongoDB爱好者
垂直技术交流平台

干货教程 | MongoDB 熟练到精通(三): 文档模型设计三步曲之基础建模·上篇

导读:本文为《MongoDB 熟练到精通》系列文章第三篇。该系列内容主要面向开发者,介绍在系统上线之前需要关注的事项,包括如何进行最关键的文档模型设计、读写事务操作,介绍数据安全和事务性等诸多高级参数和特性的含义及使用方式,以及开发者最佳实践。在最基本的数据库增删改查之余,我们更希望通过这部分的学习,让大家有足够的底气把简历上的“熟练使用 MongoDB 进行开发”,改为“精通使用 MongoDB 开发”。下面就让我们一起开启今日份的学习吧。

通过上一篇内容,我们已经初步了解了 MongoDB 学习中的一大难点——模型设计。现针对这个问题,整理总结出了可供参照跟学的方法论三步曲,帮助大家速通文档模型设计。

MongoDB 文档模型设计三步曲

上图展示了 MongoDB 文档模型设计三部曲的具体内容:基础建模、工况细化、套用设计模式。

第一步,基础建模:此时的输入来自于概念模型或逻辑模型。默认大家已经完成了针对业务需求的分析,并建立逻辑模型,明确其中的实体、表、关系等。在此基础之上,将其转化为物理的 JSON 模型,用集合或字段表现出一个基础形状。

第二步,工况细化:在第一步的基础上,进一步讨论业务完成后的具体技术需求,包括读写比例、数量等,并据此对模型进行细化和优化,使用引用和关联的方式。

第三步,套用设计模式:这一步主要基于经验或学习来达成。通过借用已有的成熟设计模式,将模型进一步优化到最终版本。

本篇我们将重点学习第一步,掌握如何建立基础文档模型,也就是历史文章中提到的三层建模中的物理模型过程。
第一步:建立基础文档模型

物理模型建立的前提是逻辑模型的输入,也即根据概念模型或业务需求推导出逻辑模型,并找到逻辑模型的对象(实体),明确实体之间的关系及基数。需要强调的是,这里的关系还包含一对一、一对多和多对多,也要分别列出。满足上述前提条件之后,就可以套用逻辑设计原则,来决定如何组织我们的 JSON 文档,并最终完成基础模型的构建。

举个例子

已知具体分步,下面就可以代入需求,依次对照模拟操作。仍然以我们的联系人管理应用为例:

 

① 找到实体对象:包含联系人、分组、地址、头像、电话等。

② 明确其间关系:以联系人与头像、地址,以及分组这三者的关系为例,可以如下列出:
  • 一个联系人有一个头像(1-1)
  • 一个联系人可以有多个地址(1-N)
  • 一个联系人可以属于多个组,一个组可以有多个联系人(N-N)
详解三种关系建模
1-1 关系建模:以 Contacts-Portraits 为例

1-1 在三种关系建模里相对简单,例如联系人和头像的关系。在 JSON 文档模型设计里,基本原则为:一对一的物理关系建模以内嵌为主,也就是将信息直接作为子文档形式,放在 JSON 母文档里,或者直接在顶级,不涉及到数据冗余。参照上图,无论头像属性有几个字段,包括图像二进制 mimetype、data ,都可以直接放到 Contacts 联系人母文档之中。MongoDB 也支持直接把二进制内容放到 JSON 文档里,不需要额外处理。这样我们就可以通过简单内存,只需要一张表,就得到了一个一对一的关系。

不过需要留意一类例外情况:对于 MongoDB 而言,文档最大限制为 16MB,所以如果内嵌后导致文档大小超过 16MB,这条原则就不太适用了(基础建模阶段,仅需了解这一限制,不用过分关注)。

1-N 关系建模:以 Contacts-Addresses 为例

类似于 1-1 关系建模,一对多关系在 MongoDB 的 JSON 文档模型设计中,同样以内嵌为主,可以以子文档方式存入,只不过因为涉及到多个元素,1-N 关系建模用数组来表示一对多关系。参照上图中联系人与地址的关系,联系人地址不唯一,符合 1-N 情境,仍然直接将 addresses 子文档字段嵌入 Contacts 母文档,字段内是一个数组,数组包含多个元素,分别是 home 家庭地址,以及 work 工作地址。通过这种方式,完美表示一个联系人可以有多个地址的关系,并且没有额外生成新表,还是一个 JSON 文档。

当然同样也会面临一些例外状况,像是数组太大,文档超过 16MB,或是长度不确定等,这些问题我们会在之后的内容中一一讲解,本篇重点关注内嵌原则。

N-N 关系建模:以 Contacts-Groups 为例

前面的内容里,我们已经了解到传统方式的 N-N 关系建模,通常用映射来表示两个实体间的 N-N 关系。但在 MongoDB 中,则无需诉诸此类关联或映射表,仍然可以通过内嵌方式来直接或间接表示,一般会用内嵌数组来表示一对多,通过冗余来实现 N-N。

参照上图,假设我们将联系人分为 Friends 组和 Surfers 组,同样可以放入母文档,如此在看到联系人的同时也获得了对应的分组信息。诚然,这种方式会出现很多冗余。但在 MongoDB 的设计中,冗余并不是“一定不可以”的存在,很多时候更是被允许甚至鼓励的。当然,这也要结合实际情况来分析,但至少在基础模型设计的第一个阶段,在没有例外情况的前提下,我们还是可以先按照这种方式把模型简单地构建好,留待后续进一步优化。

小结
到这里,大家应该不难看出,对于 MongoDB 而言,内嵌确实是建模的一大法宝及主要手段,这也是我们本篇的内容核心:基础建模本质上就是对关系的各种表达,包括一对一、一对多,以及多对多。在 MongoDB 中,基本都可以用内嵌数组的方法来完成这些关系的表述。

下一篇章我们将重点学习三步曲的第二步,工况细化,了解如何用引用或者关联来处理一些特定场景的问题。

【关联阅读】

⭐️ 碰上 MongoDB 使用问题?想要寻求更多咨询及运维帮助?这里有:
赞(4)
未经允许不得转载:MongoDB中文社区 » 干货教程 | MongoDB 熟练到精通(三): 文档模型设计三步曲之基础建模·上篇

评论 抢沙发

评论前必须登录!