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

MongoDB闪亮登场

自我介绍

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

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

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

跟关系型数据库概念对比

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

数据格式

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

{ 
    "_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自带副本集和分片,天生就适用于大数量场景,无需开发人员经过中间件去分库分表,很是方便。sql

  • 操做日志存储

不少时候,咱们须要存储一些操做日志,可能只须要存储好比最近一个月的,通常的作法是按期去清理,在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的执行原理:

i1.png

聚合内置了不少函数,使用好了这些函数咱们就能够统计出咱们想要的数据。

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

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

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

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

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

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

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

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

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

i2.png

总共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:仲裁节点自己不存储数据,只参与选举。

i3.png

Sharding

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

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

i4.png

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/个。

i5.png

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

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

知识点总结

下图是我本身总结的一些知识点,做为一个后端开发来讲,能掌握下面的内容就已经不错了,毕竟咱们又不是要去抢DBA的饭碗,若是你们业余时间要学习的话能够按照下面的点进行学习,几年前我录制了一套视频,在个人网站上,大部份内容都覆盖到了。

i6.png

工做必用

MongoDB跟Mysql的语法对比

i7.png
i8.png

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
    @GeneratedValue
    private 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

客户端推荐

下载地址:

https://studio3t.com/download/

i9.png

spring-boot-starter-mongodb-pool

最后推荐一个我本身写的小框架:Spring Boot中加强Mongodb的配置,多数据源,链接池

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

感兴趣的能够关注下个人微信公众号 猿天地,更多技术文章第一时间阅读。个人GitHub也有一些开源的代码 https://github.com/yinjihuan
相关文章
相关标签/搜索