前面我们学习了模型设计中的内嵌模式与引用模式的使用,本篇我们来看看在模型设计中如何套用常见的设计模式来降低设计难度,提高查询效率。

1 MongoDB也有设计模式?

在使用C#/Java等开发语言的时候,我们通常会学习面向对象和设计模式来提高设计水平,使得开发的应用程序具有较高的可扩展性 和 可读性。

在MongoDB的模型设计中,我们都了解到文档模型是一个无范式和无思维定式的模型,那么,有没有一些设计的套路可以像23种设计模式一样我们可以快速套用呢?

答案是:有的。

基于前人的学习和经验,我们可以适时套用,从而优化我们的文档模型设计

一个好的设计模式可以显著地:

(1)提升数据读写的效率;

(2)降低资源的需求;

2 组织结构类模式

预聚合

适用场景:

(1)热销榜:某个商品今天卖了多少,这个星期又卖了多少?...

(2)电影排行:观影者、场次统计...

(3)传统解决方案:通过聚合计算...

痛点总结:

消耗资源多,聚合(统计)时间较长。

解决方案:

一句话概括:使用预聚合字段

即 在模型中直接增加统计字段,每次更新数据时同事更新统计值。这是一种典型的以空间换时间的设计,特别适合需要较长聚合(统计)操作的场景。

示例模型:

{
product: "Bike",
sku: "abc123456",
quantitiy: 20394,
daily_sales: 40,
weekly_sales: 302,
monthly_sales: 1419
} db.inventory.update({ _id : 123 },{ $inc:
{
quantity: -1,
daily_sales: 1,
weekly_sales: 1,
monthly_sales: 1,
}
})

分桶

适用场景:

物联网场景下的海量监控数据、时序数据

比如:智慧城市、智慧交通场景下的监控数据

痛点总结:

数据点采集频繁,数据量太多,索引也很大!

解决方案:

一句话概括:分桶

即 利用文档内嵌数组,将一个时间段的数据聚合到一个文档里

示例模型:

// 分桶前:每分钟一条
{
"_id" : "20160101050000:CA2790",
"icao" : "CA2790",
"callsign" : "CA2790",
"ts" : ISODate("2016-01-01T05:00:00.000+0000"),
"events" : {
"a" : 31418,
"b" : 173,
"p" : [115, -134],
"s" : 91,
"v" : 80
}
} // 分桶后:一小时一条
{
"_id" : "20160101050000:WG9943",
"icao" : "WG9943",
"ts" : ISODate("2016-01-01T05:00:00.000+0000"),
"events" : [
{
"a" : 24293, "b" : 319, "p" : [41, 70], "s" : 56,
"t" : ISODate("2016-01-01T05:00:00.000+0000“)
},
{
"a" : 33663, "b" : 134, "p" : [-38, -30], "s" : 385,
"t" : ISODate("2016-01-01T05:00:01.000+0000“)
},
...
]
}

3 表现形式类模式

列转行

适用场景:

(1)产品(如sku)有很多属性,如 color、size、dimensions等

(2)多语言(多国家)属性等

痛点总结:

文档中有很多类似的字段,且会用于组合查询,需要建立很多的索引。

解决方案:

一句话概括:列转行

即 将列 转化为 数组,一个索引解决所有查询问题。

示例模型:

{
title: "Dunkirk",
...
release_USA: "2017/07/23", // 需要建立索引
release_UK: "2017/08/01", // 需要建立索引
release_France: "2017/08/01", // 需要建立索引
release_Festival_San_Jose: "2017/07/22" // 需要建立索引
} // 列转行后
{
title: "Dunkirk",
...
releases: [
{ country: "USA", date:"2017/07/23"},
{ country: "UK", date:"2017/08/01"}
]
} // 只需要建两个索引即可
db.movies.createIndex({“releases.country”:1, “releases.date”:1})

文档版本

适用场景:

任何有版本衍变的数据库

痛点总结:

文档模型格式多,无法知道其合理性;

升级的时候需要更新太多的文档;

解决方案:

一句话概括:增加一个版本号字段

即 快速过滤掉不需要升级的文档,升级的时候对不同版本的文档做不同的处理。

示例模型:

// 优化前:
// v1.0
{
"_id" : ObjectId("5de26f197edd62c5d388babb"),
"name" : "TJ",
"company" : "Tapdata"
} // v2.0
{
"_id" : ObjectId("5de26f197edd62c5d388babb"),
"name" : "TJ",
"company" : "Tapdata",
"wechat": "tjtang826"
} // 优化后的v2.0
{
"_id" : ObjectId("5de26f197edd62c5d388babb"),
"name" : "TJ",
"company" : "Tapdata",
"wechat": "tjtang826",
"schema_version": "2.0"
}

4 数据访问类模式

近似处理

适用场景:

(1)网页计数(每次访问一个页面都会产生一次DB计数更新操作)

(2)各种结果不需要准确的排名(统计结果的准确性并不是十分的重要)

痛点总结:

写入太频繁,消耗系统资源

解决方案:

一句话概括:近似处理(计算)

即 间隔写入,每隔10次 或 100次,大量减少写入需求。

5 总结

本文简单介绍了MongoDB的模型设计中的三大类常用设计模式:表现形式类、数据访问类 和 组织结构类。通过学习这些设计模式,使我们可以在模型设计场景中恰当地套用这些设计模式,从而达到提升数据读写效率 和 降低资源的需求,最终得到一个合适的文档模型。

下一篇,我们会学习MongoDB的索引相关知识,善用索引提高查询效率。

本系列教程目录:

MongoDB入门实战教程(1)

MongoDB入门实战教程(2)

MongoDB入门实战教程(3)

MongoDB入门实战教程(4)

MongoDB入门实战教程(5)

MongoDB入门实战教程(6)

MongoDB入门实战教程(7)

参考资料

唐建法,《MongoDB高手课》(极客时间)

郭远威,《MongoDB实战指南》(图书)

△推荐订阅学习

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

MongoDB入门实战教程(8)的更多相关文章

  1. Kafka入门实战教程(7):Kafka Streams

    1 关于流处理 流处理平台(Streaming Systems)是处理无限数据集(Unbounded Dataset)的数据处理引擎,而流处理是与批处理(Batch Processing)相对应的.所 ...

  2. ZooKeeper入门实战教程(一)-介绍与核心概念

    1.ZooKeeper介绍与核心概念1.1 简介ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务.在学习zookeeper之前,先要对分布式系统的概念有所了解,否则你将完全不知道 ...

  3. Node+Express+MongoDB+Socket.io搭建实时聊天应用实战教程(一)--MongoDB入门

    前言 本文并不是网上流传的多少天学会MongoDB那种全面的教程,而意在总结这几天使用MongoDB的心得,给出一个完整的Node+Express+MongoDB+Socket.io搭建实时聊天应用实 ...

  4. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(二)--node解析与环境搭建

    前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战.写教程一方面在自己写的过程中需要考虑更多的东西,另一方面希望能对node入门者有 ...

  5. MongoDB入门必读(概念与实战并重)

    MongoDB入门必读(概念与实战并重) 一.概述 MongoDB是一个基于分布式文件存储的数据库开源项目.由C++语言编写.旨在为WEB应用提供可护展的高性能数据存储解决方案. MongoDB是一个 ...

  6. mybatis实战教程(mybatis in action),mybatis入门到精通

    转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加 ...

  7. mybatis实战教程(mybatis in action),mybatis入门到精通(转)

    转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加 ...

  8. mongodb入门教程二

    title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...

  9. mongodb入门教程

    title: mongodb入门教程 date: 2016-04-06 14:47:18 tags: --- 为什么要认识呢,因为这玩意就一傻逼 借用一下百科的介绍 MongoDB 是一个介于关系数据 ...

  10. MongoDb 入门教程

    MongoDb 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 它是可扩展的高性能数据存储解决方案,经常被用于非关系型数据的存储,能存储海量的数据. 常 ...

随机推荐

  1. MySQL-事务相关知识

    事务ACID的理解 引入事务的主要目的: 保证数据库从一个一致性状态切换为另一种一致性状态 所有修改要么都保存,要么都不保存 A 原子性 原子性关注单个事务的整体性,需要保证事务中的全部操作是一个单元 ...

  2. 2025成都.NET开发者Connect圆满结束

    大家好,我是Edison. 2025年成都.NET开发者Connect线下聚会活动于3月29日圆满结束,本次活动吸引了约30位.NET开发者朋友参与,他们分别来自成都各家技术公司,我们相聚城南华府国际 ...

  3. DRG,医改分水岭!

    2020-11-04 (2021年政府推出2.0版DRG.增加MCC和CC,各自政府的医保支付中增加了人性化的支付倍率的处理) 假设某疾病病组支付标准10000元,患者自付自费比例40%,分三种情况, ...

  4. 物理机burpsuite抓包虚拟机以及Chrome导入burp证书

    记录物理机的burpsuite抓包虚拟机谷歌浏览器和遇到的问题总结 从别的地方搬家过来的,图片有水印懒得改了就这样吧,或者改天抹了( 打开虚拟机,网络适配器选择NAT 打开主机的burpsuite,点 ...

  5. socket tcp断线重连

    一.网上常用方法1.当Socket.Conneted == false时,调用如下函数进行判断 点击(此处)折叠或打开 /// <summary> /// 当socket.connecte ...

  6. RL · Exploration | 使用时序距离构造 intrinsic reward,鼓励 agent 探索

    论文标题:Episodic Novelty Through Temporal Distance. ICLR 2025,8 8 6 5 poster. arxiv:https://arxiv.org/a ...

  7. 阿里云服务器中Linux下centos7.6安装mysql8.0.11

    1.下载安装 MySQL最新下载地址:https://dev.mysql.com/downloads/mysql/  选择的是Linux 64位通用的二级制版本,这样不在需要进行编译安装,系统安装依赖 ...

  8. DPDI online在线调度系统环境部署

    DPDI online简介: DPDI Online 是一款基于Kettle的强大在线任务调度平台,凭借其高效与灵活性,专为调度和监控Kettle客户端生成的ETL任务而设计 DPDI online部 ...

  9. 题解:P10858 [HBCPC2024] Long Live

    给你两个数 x,yx,yx,y 让你找到一组 a,ba,ba,b,使 lcm⁡(x,y)gcd⁡(x,y)=ab\sqrt{\frac{\operatorname{lcm}(x,y)}{\gcd(x, ...

  10. GitLab整体迁移到其他服务器的方法与步骤

    将 GitLab 整体迁移到其他服务器上,可以分为以下几个主要步骤,以确保数据和配置的完整性: 1. 备份当前 GitLab 实例 在原服务器上,执行 GitLab 自带的备份命令,以备份所有数据(如 ...