MongoDB高手课_MongoDB_NoSQL-极客时间极客时间推出的MongoDB高手课是帮助互联网从业者学习MongoDB、NoSQL的在线课程,极客时间是面向IT领域的知识服务产品,致力于帮助用户轻松学习,高效学习。https://time.geekbang.org/course/intro/100040001?tab=catalog

一. 传统模型设计

 1. 数据模型设计三要素:实体(Entity),属性(Attribute),关系(Relationship)

2. 传统模型设计流程(模型逐步细化的过程):概念模型==>逻辑模型==>物理模型

        关系模型常用的第三范式原则:数据在库中尽量不存在冗余,指表中的所有数据元素要能唯一地被主关键字所标识,它们之间必须相互独立,不存在其他的函数关系。


二. JSON文档模型设计

1. 文档模型和关系模型的区别

  • 文档模型设计:属于物理模型(PDM)设计阶段,但其实文档模型设计的物理模型和逻辑模型相似,可以省略物理建模的具体过程。
  • 文档模型设计vs关系模型设计区别:文档模型设计不遵从第三范式,允许冗余。
  • 文档模型设计原则:性能(performance)、开发易用(ease of development)。
  • 文档模型vs关系模型:

 2. MongoDB文档模型设计三部曲

文档模型设计示例见如下文章:

《MongoDB高手课》学习记录(第十四天) - SegmentFault 思否今天要学习的是14、15、16、17章节。对比传统的模型设计方法,作者总结自己的经验,来讲解MongoDB是怎么样进行模型设计的,并举了一个分桶模型的例子。https://segmentfault.com/a/1190000021459458?utm_source=sf-similar-article

(1)基础建模

        找到对象(实体)==> 明确关系(实体之间的关系及基数)==> 进行建模(基于关系建模原则确定内嵌方式)==> 完成基础模型构建

关系建模原则【以内嵌为主】:

  • 1-1:以内嵌为主,作为子文档或者直接在顶级,不涉及数据冗余。
    • 例外:内嵌后文档大小超过16MB。
  • 1-N:以内嵌为主,用数组表示一对多,不涉及数据冗余。
    • 例外:内嵌后文档大小超过16MB or 数组长度太大 or 数组长度不确定。
  • N-N:无需映射表,以内嵌为主,用数组表示一对多,用冗余实现多对多。
    • 例外:内嵌后文档大小超过16MB or 数组长度太大 or 数组长度不确定。

(2)工况细化

基于内嵌的文档模型,根据实际使用场景的技术需求:

  • 使用冗余优化访问性能
  • 使用引用解决性能瓶颈
    • 引用:类似关系模型设计,用id或唯一键关联,用 $lookup 一次查询多表。
    • 使用场景:内嵌后文档大小超过16MB or 内嵌文档或数组元素需频繁修改 or 数组长度太大 or 数组长度不确定。
    • 引用设计限制:(1)MongoDB对使用引用的集合之间无主外键检查;(2)$lookup 只支持left outer join,且关联目标(from)不能是分片表。

引用案例: 

引用模式下的关联查询:

# 使用$lookup对两个表进行关联查询
# 本地表contacts的group_ids字段和目标表groups的group_id字段一对一对应
db.contacts.aggregate([
    {
        $lookup:{
            from:"groups",              //指明哪个是目标表
            localField:"group_ids",     //本地表取哪个字段
            foreignField:"group_id',    //目标表取哪个字段
            as:"groups"                 //拿回来之后放到groups这个新字段名中
       }
    }     
])

(3)套用设计模式

  • 设计模式:经过实战的优秀设计技巧,可以解决很多常见问题,提升数据读写效率,降低资源需求。
  • 文档模型无范式、无思维定式,可以充分发挥开发者的想象力,与设计模式相结合可以事半功倍。

MongoDB常见设计模式

【例1】列转行设计模式:

 【例2】文档版本设计模式:

【例3】近似字段设计模式: increment by

 【例4】预聚合设计模式: 

【例5】分桶设计模式:

参考文章:

《MongoDB高手课》学习记录(第十五天) - SegmentFault 思否以存储电影信息的文档为例,因为各个国家的首映时间不同,我们的最简单的想法可能为了统计方便,会每增加一个上映地点,就增加一个统计字段,然后再给这个字段建一个索引。这样统计查询的速度是快了,但是系统写入的效率却下降了。那么怎么解决这个问题呢?采用内嵌数组的方式来组织数据,减少字段数量。然后通过建立内...https://segmentfault.com/a/1190000021471814?utm_source=sf-similar-article