# 内嵌

## 一个联系人管理应用的例子

1. 找到对象
   - Contacts
   - Groups
   - Address
   - Portraits
   
2. 明确关系

   - 一个联系人有一个头像（1-1）
   - 一个联系人可以有多个地址（1-N）
   - 一个联系人可以属于多个组，一个组可以有多个联系人（N-N）

3. 模型关系图

   ![image-20200714193458986](../img/modeling/img_14.png)

## 1-1关系建模：portraits

- 基本原则

  1. 一对一关系以内嵌为主
  2. 作为子文档形式或者直接在顶级
  3. 不涉及到数据冗余

- 例外情况

  1. 如果内嵌后导致文档大小超过`16MB`
  2. 超过`16MB`还是尽量将字段抽出来单独做表

- 模型图

  ![image-20200714194052741](../img/modeling/img_15.png)

## 1-N关系建模：Addresses

- 基本原则

  1. 一对多关系同样以内嵌为主
  2. 用数组来表示一对多
  3. 不涉及到数据冗余

- 例外情况

  1. 内嵌后导致文档大小超过`16MB`
  2. 数组长度太大（数万或更多）
  3. 数组长度不确定

- 模型图

  ![image-20200714194249256](../img/modeling/img_16.png)

## N-N关系建模：内嵌数组模式

- 基本原则

  1. 不需要映射表
  2. 一般用内嵌数组表示一对多
  3. 通过冗余来实现N-N

- 例外情况

  1. 内嵌后导致文档大小超过`16MB`
  2. 数组长度太大（数万或更多）
  3. 数组长度不确定

- 模型图

  ![image-20200714194516357](../img/modeling/img_17.png)

## 模式小结：内嵌

- `90：10规则`: 大部分时候你会使用内嵌来表示`1-1`，`1-N`，`N-N`
- 内嵌类似于预先聚合（关联）
- 内嵌后对读操作通常有优势（减少关联）