来自:猿天地

MongoDB 闪亮登场

自我介绍

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

MongoDB 最大的特点就是无 Schema 限制,灵活度很高。数据格式是 BSON,BSON 是一种类似 JSON 的二进制形式的存储格式,简称 Binary JSON 它和 JSON 一样,支持内嵌的文档对象和数组对象。

跟关系型数据库概念对比

Mysql MongoDB
Database(数据库) Database(数据库)
Table(表) Collection(集合)
Row(行) Document(文档)
Column(列) Field(字段)

数据格式

MongoDB 将数据存储为一个文档,BSON 格式。由 key 和 value 组成。

{ "_id" : ObjectId("5e141148473cce6a9ef349c7"),"title" : "批量更新", "url" : "http://cxytiandi.com/blog/detail/8", "author" : "yinjihuan", "tags" : ["java", "mongodb", "spring"], "visit_count" : NumberLong(10), "add_time" : ISODate("2019-02-11T07:10:32.936+0000")
}

使用场景

  • 大数据量存储场景

MongoDB 自带副本集和分片,天生就适用于大数量场景,无需开发人员通过中间件去分库分表,非常方便。

  • 操作日志存储

很多时候,我们需要存储一些操作日志,可能只需要存储比如最近一个月的,一般的做法是定期去清理,在 MongoDB 中有固定集合的概念,我们在创建集合的时候可以指定大小,当数据量超过大小的时候会自动移除掉老数据。

  • 爬虫数据存储

爬下来的数据有网页,也有 Json 格式的数据,一般都会按照表的格式去存储,如果我们用了 MongoDB 就可以将抓下来的 Json 数据直接存入集合中,无格式限制。

  • 社交数据存储

在社交场景中使用 MongoDB 存储存储用户地址位置信息,通过地理位置索引实现附近的人,附近的地点等。

  • 电商商品存储

不同的商品有不同的属性,常见的做法是抽出公共的属性表,然后和 SPU 进行关联,如果用 MongoDB 的话那么 SPU 中直接就可以内嵌属性。

自我陶醉

MongoDB 的功能点很多,但是大部分场景下我们只用了最简单的 CRUD 操作。下面隆重的介绍下 MongoDB 的功能点,就像你去相亲一样,不好好介绍自己的优点又怎能让你对面的菇凉心动呢?

CRUD

CRUD 也就是增删改查,这是数据库最基本的功能,查询还支持全文检索,GEO 地理位置查询等。

  • db.collection.insertOne()

单个文档插入到集合中

  • db.collection.insertMany()

多个文档插入到集合中

  • db.collection.insert()

单个或者多个文件插入到集合中

  • db.collection.find( )

查询数据

  • db.inventory.updateOne()

更新单条

  • db.inventory.updateMany()

更新多条

  • db.inventory.deleteOne( )

删除单条文档

  • db.inventory.deleteMany()

删除多条文档

Aggregation

聚合操作用于数据统计方面,比如 Mysql 中会有 count,sum,group by 等功能,在 MongoDB 中相对应的就是 Aggregation 聚合操作。

聚合下面有两种方式来实现我们需要对数据进行统计的需求,一个是 aggregate,一个是 MapReduce。

下图展示了 aggregate 的执行原理:

aggregate执行原理

聚合内置了很多函数,使用好了这些函数我们就可以统计出我们想要的数据。

$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。

:用于过滤数据,只输出符合条件的文档。match 使用 MongoDB 的标准查询操作。

$limit:用来限制 MongoDB 聚合管道返回的文档数。

$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。

$group:将集合中的文档分组,可用于统计结果。

$sort:将输入文档排序后输出。

$geoNear:输出接近某一地理位置的有序文档。

$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。

下图展示了 MapReduce 的执行原理:

mapReduce执行原理

总共 4 条数据,query 指定了查询条件,只处理 status=A 的数据。

map 阶段对数据进行分组聚合,也就是形成了第三部分的效果,根据 cust_id 去重统计。

reduce 中的 key 也就是 cust_id, values 也就是汇总的 amount 集合。然后进行 sum 操作,最终的结果通过 out 输出到一个集合中。

Transactions

MongoDB 最开始是不支持事务的,在 MongoDB 中,对单个文档的操作是原子性操作。所以再设计的时候可以使用嵌入的文档和数组来描述数据之间的关系,这样就不用跨多个文档和集合进行操作,也就通过了单文档原子性消除了许多实际用例对多文档事务的需要。

任何事物都是有限制的,某些场景还是不能完全通过内嵌的方式来描述数据的关系,还是会存在多个集合,对于使用 MongoDB 的用户来说,如果能支持事务就很方便了。

不负众望,MongoDB 4.0 版本的发布,为我们带来了原生的事务操作。

Indexes

索引不用我多说了,作用大家都知道。单索引,组合索引,全文索引,Hash 索引等。

db.collection.createIndex({user_id: 1, add_time: 1}, {background: true}
)

创建索引特别要注意的是将 background 设置为 true,在建索引的过程会阻塞其它数据库操作,background 可指定以后台方式创建索引,默认为 false。这可是血的教训呀,切记切记。

Security

MongoDB 中的安全需要重视,目前启动不知道有没有强制的限制,以前启动的时候可以不指定认证的方式,也就是不需要密码即可访问,然后很多人都直接用的默认端口,暴露在公网上,给不法分子有机可乘,出现了数据被删,需要用比特币来找回数据的案例比比皆是。

还是要开启安全认证,内置了很多角色,不同的角色可操作的内容不一样,控制的比较细。

Replication

副本集是一组相同数据集的 MongoDB 实例,同时在多个节点存储数据,提高了可用性。主节点负责写入,从节点负责读取,提高整体性能。

副本集由下面的组件构成:

Primary:主节点接收所有的写操作。

Secondaries:从节点会从主节点进行数据的复制,维护跟主节点相同的数据。用于查询操作。

Arbiter:仲裁节点本身不存储数据,只参与选举。

副本集架构

Sharding

分片是 MongoDB 绝对的亮点,将数据水平拆分到多个节点。MongoDB 的分片是全自动的,我们只需要配置好分片的规则,它就能自动维护数据并存储到不同节点。MongoDB 使用分片来支持大数据量的存储和高吞吐量的操作。

下图是 Mongodb 的分片集群架构图:

sharding架构

MongoDB 分片集群由以下组件够成:

Shard:每个 shard 的数据都是独立完整的一份。并且可以作为副本集部署。

mongos:mongos 是查询路由器,在客户端和服务端中间的一层,请求会直接到 mongos,由 mongos 路由到具体的 Shard。

Config Servers:存储集群所有节点、分片数据路由信息。

GridFS

GridFS 是 MongoDB 的一个子模块,主要用于在 MongoDB 中存储文件,相当于 MongoDB 内置的一个分布式文件系统。

本质上还是讲文件的数据分块存储在集合中,默认的文件集合分为 fs.files 和 fs.chunks。

fs.files 是存储文件的基本信息,比如文件名,大小,上传时间,md5 等。fs.chunks 是存储文件真正数据的地方,一个文件会被分割成多个 chunk 块进行存储,一般为 256k/个。

GridFS文件存储格式

如果你的项目中用到了 MongoDB,那么你可以使用 GridFS 来构建一个文件系统,这样就不用去购买第三方的存储服务了。

GridFS 的好处是你不用单独去搭建一个文件系统,直接使用 Mongodb 自带的即可,备份,分片都依赖 MongoDB,维护起来也方便。

知识点总结

下图是我自己总结的一些知识点,作为一个后端开发来说,能掌握下面的内容就已经不错了,毕竟我们又不是要去抢 DBA 的饭碗,如果大家业余时间要学习的话可以按照下面的点进行学习,几年前我录制了一套视频,在我的网站上,大部分内容都覆盖到了。

MongoDB知识点汇总

工作必用

MongoDB 跟 Mysql 的语法对比

Spring Boot 中集成 MongoDB

加入 MongoDB 的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置 MongoDB 的信息:

spring.data.mongodb.database=test
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
// 用户名,密码省略.......

直接注入 MongoTemplate 就可以操作 MongoDB:

@Autowired
private MongoTemplate mongoTemplate;

使用示列

创建一个实体类,对应 MongoDB 的集合

@Data
@Document(collection = "article_info")
public class Article {@Id@GeneratedValueprivate Long id;@Field("title")private String title;@Field("url")private String url;@Field("author")private String author;@Field("tags")private List<String> tags;@Field("visit_count")private Long visitCount;@Field("add_time")private Date addTime;
}

最终存储到数据中的格式如下:

{ "_id" : ObjectId("5e141148473cce6a9ef349c7"),"title" : "批量更新", "url" : "http://cxytiandi.com/blog/detail/8", "author" : "yinjihuan", "tags" : ["java", "mongodb", "spring"], "visit_count" : NumberLong(10), "add_time" : ISODate("2019-02-11T07:10:32.936+0000")
}

插入数据

Article article = new Article();
article.setTitle("MongoTemplate 的基本使用 ");
article.setAuthor("yinjihuan");
article.setUrl("http://cxytiandi.com/blog/detail/1");
article.setTags(Arrays.asList("java", "mongodb", "spring"));
article.setVisitCount(0L);
article.setAddTime(new Date());
mongoTemplate.save(article);

数据库语法

db.article_info.save({"title": "批量更新","url": "http://cxytiandi.com/blog/detail/8","author": "yinjihuan","tags": ["java","mongodb","spring"],"visit_count": NumberLong(10),"add_time": ISODate("2019-02-11T07:10:32.936+0000")
})

更新数据

Query query = Query.query(Criteria.where("author").is("yinjihuan"));
Update update = Update.update("title", "MongoTemplate").set("visitCount", 10);
mongoTemplate.updateMulti(query, update, Article.class);

数据库语法

db.article_info.updateMany({"author":"yinjihuan"}, {"$set":{"title":"MongoTemplate", "visit_count": NumberLong(10)}}
)

删除数据

Query query = Query.query(Criteria.where("author").is("yinjihuan"));
mongoTemplate.remove(query, Article.class);

数据库语法

db.article_info.remove({"author":"yinjihuan"})

查询数据

Query query = Query.query(Criteria.where("author").is("yinjihuan"));
List<Article> articles = mongoTemplate.find(query, Article.class);

数据库语法

db.article_info.find({"author":"yinjihuan"})

存储文件

File file = new File("/Users/yinjihuan/Downloads/logo.png");
InputStream content = new FileInputStream(file);
// 存储文件的额外信息,比如用户ID,后面要查询某个用户的所有文件时就可以直接查询
DBObject metadata = new BasicDBObject("userId", "1001");
ObjectId fileId = gridFsTemplate.store(content, file.getName(), "image/png", metadata);

源码参考

https://github.com/yinjihuan/spring-cloud/tree/master/Spring-Cloud-Book-Code-2/ch-17/mongodb[1]

客户端推荐

下载地址:

https://studio3t.com/download/[2]

MongoDB客户端

spring-boot-starter-mongodb-pool

最后推荐一个我自己写的小框架:Spring Boot 中增强 Mongodb 的配置,多数据源,连接池

https://github.com/yinjihuan/spring-boot-starter-mongodb-pool[3]

参考资料

[1]

mongodb: https://github.com/yinjihuan/spring-cloud/tree/master/Spring-Cloud-Book-Code-2/ch-17/mongodb

[2]

studio3t: https://studio3t.com/download/

[3]

spring-boot-starter-mongodb-pool: https://github.com/yinjihuan/spring-boot-starter-mongodb-pool

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

恕我直言,牛逼哄哄的MongoDB你可能只会30%相关推荐

  1. 牛逼哄哄的SLAM技术 即将颠覆哪些领域?

    牛逼哄哄的SLAM技术 即将颠覆哪些领域? 0评论 2016-05-12 21:15:02 来源:雷锋网 作者:宗仁 一般人我不告诉他,绝佳买入机会! 什么是SLAM?机器人在未知环境中,要实现智能化 ...

  2. 牛逼哄哄的SLAM技术即将颠覆哪些领域

    原标题:牛逼哄哄的SLAM技术即将颠覆哪些领域? 什么是SLAM?机器人在未知环境中,要实现智能化需要完成三个任务,第一个是定位(Localization),第二个是建图(Mapping),第三个则是 ...

  3. java swing 动态生成表格_6 个曾经牛逼哄哄的 Java 技术,你用过吗?

    大家好啊,今天给大家分享下我的开发历程中,我知道的那些被淘汰的技术或者框架,有些我甚至都没有用过,但我知道它曾经风光过. 废话不多说,下面我要开始吹了-- 1.Swing 下面这个是用 swing 开 ...

  4. ios安卓模拟器_IOS全球首款手游模拟器,牛逼哄哄但没有卵用!

    分享IOS和MAC少有人知的软件 100000+果粉都在看    关注 1 黑雷模拟器是什么? 最近看到很多平台都在发布这款苹果模拟器,看了很多文章不得不说都是一些假果粉,很多应该就是为了蹭热点,对这 ...

  5. 牛逼哄哄的全链路监控系统!搭建起来也没有想象中的那么难啊...

    点击关注公众号,回复"1024"获取2TB学习资源! 问题背景 随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务.互联网应用构建在不同的软件模块集上 ...

  6. 牛逼哄洪的 Java 8 Stream,性能也牛逼么?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Java8的Stream API可以极大提高Java程序员的生产力 ...

  7. GitHub 上 6 款牛哄哄的后台模板

    今日推荐 一个基于SpringBoot+Vue的百度网盘高仿项目 一个Github项目搞定微信.QQ.支付宝等第三方登录 推荐 7 个牛哄哄 Spring Cloud 实战项目 一套既美观又方便的后台 ...

  8. 【牛哄哄】正版WINDOWS长啥样

    "老板,来瓶茅台!"新年将至,新朋老友来聚会,前天晚上猪哼哼算了一宿的帐,收入颇令自己满意,今天出手自然阔绰起来. "猪先生,请问你是要真货,还是要水货,水货价格很便宜的 ...

  9. 你知道牛X哄哄帕斯卡计算器吗?

    这台机器应该是人类史上第一台能做加减法的机械计算器.好牛X,被冠以第一台头衔. 布莱兹·帕斯卡(Blaise Pascal)这货在科学的历史上是一个牛气冲天,牛X哄哄的人.如何"牛气冲天,牛 ...

最新文章

  1. Docker学习(八)-----Docker安装mysql
  2. 【JOURNAL】恭喜发财
  3. 观点 | 哈哈,TensorFlow被吐槽了吧
  4. Linux字符设备驱动结构
  5. Next.js踩坑入门系列(七) —— 其他相关知识
  6. 测试Live Writer 发表博客
  7. LeetCode 1706. 球会落何处(模拟)
  8. html安卓手机打开后只有半屏,宽度设置100%在移动端时变成一半
  9. aide入侵检测工具与crontab
  10. 神奇 | 神奇,原来 Linux 终端下还有这两种下载文件方式
  11. dijkstra伪代码翻译java,Dijkstra算法的伪代码和C语言版本,还是模版
  12. 最新抗灾诗作:生死不离
  13. Tree树结构java实现
  14. 一个简单的中文自动转拼音
  15. 第九课 go的循环语句
  16. 微信小程序-视频教程-链接地址
  17. 如何学好3D引擎编程
  18. 北斗导航 | dBW/dBm/W快速换算方法
  19. 每日英语-20171115
  20. python产品质量分析报告范文_Python Jinja2 徒手生成数据分析报告

热门文章

  1. 4道经典指针笔试题讲解 ~
  2. 关于NameError: name ‘train_test_split‘ is not defined错误提示
  3. 线段树分裂与合并 ---- 树上差分 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
  4. 使用MarkDown编辑器做出有意思的柱状图(完整代码)
  5. 习题3-3 数数字(Digit Counting , ACM/ICPC Danang 2007, UVa1225)
  6. 列举窗体控制台应用程序中的3中控件_今天来点枯燥的,Visual C#的Windows窗体运行过程...
  7. docx文件上传java_java上传文件通过mybatis存储到数据库的blob格式中.docx
  8. controller如何保证当前只有一个线程执行_今天我们来聊一聊 Spring 中的线程安全性...
  9. [jdk8]Predicate 函数式接口
  10. 为什么你写的代码糟透了?