# 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

# 1-N 关系建模

基本原则:一对多的关系同样以内嵌为主,用数组来表示一对多,不会涉及到数据冗余。

比如,一个人会有多个收货地址:

// contacts
{
    name: "stanxing",
    addresses: [
        {type: "home", location: "xxx"},
        {type: "work", location: "xxx"}
    ]
}
1
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

# 第二步,工况细化

根据业务的实际情况来判断内嵌数组是否会引起问题?如果数组大小不确定,或者数组太大而且频繁更改,依然可以选择使用引用来达到分表的目的。看下面几个例子:

  • 联系人的分组信息很大,而且频繁修改:如果通过内嵌完成,每次更新一个分组信息,就会对所有人进行更新,造成很大的写入压力,因此应该单独对分组信息存入一个表。
  • 内嵌文档太大,比如内嵌的是交易数据,一直在增加而且无限制:不应该使用内嵌文档,应该单独拆分出一个表来存储,通过引用关联。

# 第三部,套用设计模式

TODO

上次更新: 5/12/2020, 2:19:47 AM