# MongoDB 模型设计
# 误区
- MongoDB 不需要模型设计(当然需要,任何程序开发都应该先定义 schema 文档,只不过 MongoDB 没有强约束来限制数据库内的字段)
- MongoDB 应该用一个超级大的文档来组织所有的数据(当然不行,MongoDB 文档限制最大 16MB,显然不可能无限嵌套)
# 文档模型设计
- 文档模型的设计实际是物理模型的设计阶段。
- JSON 文档模型通过内嵌数组和引用字段来表示关联关系
- 文档模型设计不遵循第三范式,允许冗余
# 设计原则
- 性能
- 开发易用
# 第一步,基础建模
- 建立基础文档模型:
- 根据概念或者业务需求推导出逻辑模型,即 JSON 对象
- 列出实体之间的关系,即明确关系(1-1,1-N 还是 N-1)
- 套用逻辑设计原则来决定内嵌方式,进行建模
- 完成基础模型构建,即完成集合,文档,字段的构建
# 1-1 关系建模
基本原则:一对一的关系建模以内嵌为主,作为子文档形式,或者直接在顶级,不会涉及到数据冗余。
比如,一个联系人有一个头像,这是一一对应的:
// contacts
{
"name":"stanxing",
portraits: {
mimetype: xxx,
data: xxx,
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1-N 关系建模
基本原则:一对多的关系同样以内嵌为主,用数组来表示一对多,不会涉及到数据冗余。
比如,一个人会有多个收货地址:
// contacts
{
name: "stanxing",
addresses: [
{type: "home", location: "xxx"},
{type: "work", location: "xxx"}
]
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# N-N 关系建模
基本原则:不需要映射表,一般用内嵌数组来表示多对多,通过冗余来实现 N-N。
比如,一个人可以加入多个联系组,一个联系组又会有多个联系人:
// contacts
{
name: "stanxing",
groups: [
{ name: "Friends" },
{ name: "Surfers" }
]
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 第二步,工况细化
根据业务的实际情况来判断内嵌数组是否会引起问题?如果数组大小不确定,或者数组太大而且频繁更改,依然可以选择使用引用来达到分表的目的。看下面几个例子:
- 联系人的分组信息很大,而且频繁修改:如果通过内嵌完成,每次更新一个分组信息,就会对所有人进行更新,造成很大的写入压力,因此应该单独对分组信息存入一个表。
- 内嵌文档太大,比如内嵌的是交易数据,一直在增加而且无限制:不应该使用内嵌文档,应该单独拆分出一个表来存储,通过引用关联。
# 第三部,套用设计模式
TODO