MongoDB 规范化还是嵌套
Embed when data is read together in most cases
- Embedded data models are often denormalized, because frequently-accessed data is duplicated in multiple collections
- Query on Embedded/Nested Documents
Reference when data is read together “sometimes”
- To query normalized data in multiple collections, MongoDB provides
$lookup
aggregation stage
你可以尝试搜索:
-
MongoDB references vs embedding
-
MongoDB normalization vs denormalization
-
MongoDB nested documents vs separate collections
-
MongoDB schema design
-
MongoDB aggregation lookup vs embedded
总结一下也很简单, 当系统结构简单, 子文档也很小的时候, 可以不用规范化, 直接嵌套, 比如用户里面直接嵌入地址信息, 地址嘛, 也不会很大, 获取用户信息的时候, 直接一个 document 什么都有了, 减少连表查询, 速度也很快,
但系统复杂的时候, 比如多对多关系, 很多表需要相互关联, 需要经常修改, 这个时候就不可以嵌套了, 比如我们需要经常修改商品信息, 或者商品的评论信息, 这个时候就不可以采用 把 评论 嵌入 商品, 把商品嵌入商店, 因为这样, 每次你修改评论, 都需要去查找商店, 然后对应的商品, 然后去修改对应的评论, 这肯定不高效, 不如使用规范化, 直接根据评论 id 去更新数据,
MongoDB 没有传统数据库中 join 操作和 foreign key, 但可以通过 embedded documents 或者 reference 来表示一对多关系, 也可使用聚合管道
$lookup
来实现类似 Join 的功能, 但注意$lookup
只适用于 Reference 存储的查询, 而不是嵌套文档, 上面已经给出了两种方法具体的查询方式
至于规范化的设计, 一般有两种存储
- 商店添加一个数组字段存储拥有的商品 id
- 商品添加一个字段, 标注其所属的 id
前者需要使用 MongoDB 的数组查询, 后者使用 $lookup
聚合管道查询, 这都是规范化的设计, 至于哪个更好, 要看具体的场景, 注意想要查询效率, 就要接受一定程度数据冗余, 当然有了冗余, 不仅仅是占用空间的问题, 还存在更新的问题, 比如商店存储其拥有的所有商品 id 或者 name 这就是冗余, 因为可以直接通过 商品 collection 查询到某个商店的所有商品, 那为什么会导致更新问题呢?
- 当商品的名字更新的时候, 商店若存了所拥有的所有商品名字列表, 是不是也需要更新这个数组?
- 当商品被删除下架的时候, 是不是也要处理商店的商品名字列表?