2. MongoDB入门

在探花交友APP中,会涉及很多的数据保存,比如用户的动态,点赞信息,评论信息,位置信息等。这些数据有一下的特点:

  • 海量数据
  • 读多写少
  • 数据价值低
  • 地址位置相关数据
  • 更新十分频繁

针对上述特点,传统的MySQL数据库有些力不从心,因此,我们引入了MongoDB。

2.1 MongoDB简介

MongoDB:是一个高效的非关系型数据库(不支持表关系:只能操作单表)

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

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。

MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

2.1.1 MongoDB的存储模型


MongoDB采用的是内存和磁盘结合的存储方式,比较常用的数据都保存在内存中,如果内存中找不到数据,再去磁盘中查找,这样就加快了查询的速度。

为了保证数据的安全性,内存中的数据每一分钟都会同步到磁盘中。
此外,为了更加保护数据的安全性,MongoDB在新版本中引入了日志,日志在内存和硬盘中各一份,每10ms同步一次。这样即使断电的时候,内存中的数据没有保存到磁盘,也可以通过日志文件进行恢复,从而保证了数据的安全性。

但是即使这样,也不能MongoDB不能够保证数据100%不丢失。


此外,MongoDB支持数据分页技术,可以将保存的数据进行分页,从而可以非常方便的进行存储容量的扩充

2.1.2 MongoDB与其他数据库对比

  • 和Redis对比

    • Redis是纯内存数据库,存储容量有限
    • Redis支持的查询比较简单,而MongoDB支持结构化查询
  • 和MySQL对比
    • MongoDB不支持事务和联表查询
    • MongoDB支持动态字段,MySQL数据表一旦创建,很难修改字段
  • 查询效率
    • Redis > MongoDB > MySQL

2.1.3 MongoDB的应用

  • 游戏装备数据

    • 特征:修改频率很高
  • 物流行业数据
    • 特征:地理位置信息,海量数据
  • 直播打赏数据
    • 特征:数据量很大,修改频繁
  • 日志数据
    • 特征:数据量大,结构多变

2.2 MongoDB的数据和体系结构

下面是MongoDB和MySQL数据库概念上的对比

MongoDB中存储BSON数据,类似JSON

MongoDB 的逻辑结构是一种层次结构。主要由: 文档(document)、集合(collection)、数据库(database)这三部分组成的。逻辑结构是面 向用户的,用户使用 MongoDB 开发应用程序使用的就是逻辑结构。

  1. MongoDB 的文档(document),相当于关系数据库中的一行记录。
  2. 多个文档组成一个集合(collection),相当于关系数据库的表。
  3. 多个集合(collection),逻辑上组织在一起,就是数据库(database)。
  4. 一个 MongoDB 实例支持多个数据库(database)。 文档(document)、集合(collection)、数据库(database)的层次结构如下图:


为了更好的理解,下面与SQL中的概念进行对比:

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 表中的一条数据
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

MongoDB中常用的数据结构如下:

MongoDB中常见的数据类型有:

  • 数据格式:BSON {aa:bb}
  • null:用于表示空值或者不存在的字段,{“x”:null}
  • 布尔型:布尔类型有两个值true和false,{“x”:true}
  • 数值:shell默认使用64为浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用 NumberInt(4字节符号整数)或NumberLong(8字节符号整数), {“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
  • 字符串:UTF-8字符串都可以表示为字符串类型的数据,{“x”:“呵呵”}
  • 日期:日期被存储为自新纪元依赖经过的毫秒数,不存储时区,{“x”:new Date()}
  • 正则表达式:查询时,使用正则表达式作为限定条件,语法与JavaScript的正则表达式相 同,{“x” : /[abc]/}
  • 数组:数据列表或数据集可以表示为数组,{“x”: [“a“,“b”,”c”]}
  • 内嵌文档:文档可以嵌套其他文档,被嵌套的文档作为值来处理,{“x”:{“y”:3 }}
  • 对象Id:对象id是一个12字节的字符串,是文档的唯一标识,{“x”: objectId() }
  • 二进制数据:二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要 将非utf-字符保存到数据库中,二进制数据是唯一的方式。

2.3 MongDB的简单操作操作

2.3.1 新增数据

在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)。

#插入数据
#语法:db.表名.insert(json字符串)
db.user.insert({id:1,name:'zhangsan'})  #插入数据

2.3.2 更新数据

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(<query>,<update>,[upsert: <boolean>,multi: <boolean>,writeConcern: <document>]
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如 , , ,inc.$set)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。
#更新数据
> db.user.update({id:1},{$set:{age:22}}) #注意:如果这样写,会删除掉其他的字段
> db.user.update({id:1},{age:25})#更新不存在的字段,会新增字段
> db.user.update({id:2},{$set:{sex:1}}) #更新数据#更新不存在的数据,默认不会新增数据
> db.user.update({id:3},{$set:{sex:1}})#如果设置第一个参数为true,就是新增数据
> db.user.update({id:3},{$set:{sex:1}},true)

2.3.3 删除数据

通过remove()方法进行删除数据,语法如下:

db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <document>}
)

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

实例:

#删除数据
> db.user.remove({})#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})> db.user.remove({age:22},true)#删除所有数据
> db.user.remove({})

2.3.4 查询数据

MongoDB 查询数据的语法格式如下:

db.user.find([query],[fields])
  • query :可选,使用查询操作符指定查询条件
  • fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
    条件查询:
操作 格式 范例 RDBMS中的类似语句
等于 {<key>:<value>} db.col.find({"by":"Jack"}).pretty() where by = 'Jack'
小于 {<key>:{$lt:<value>}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
小于或等于 {<key>:{$lte:<value>}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
大于 {<key>:{$gt:<value>}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
大于或等于 {<key>:{$gte:<value>}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
不等于 {<key>:{$ne:<value>}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50

实例:

#插入测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})db.user.find()  #查询全部数据
db.user.find({},{id:1,username:1})  #只查询id与username字段
db.user.find().count()  #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2#分页查询:Skip()跳过几条,limit()查询条数
db.user.find().limit(2).skip(1)  #跳过1条数据,查询2条数据
db.user.find().sort({id:-1}) #按照id倒序排序,-1为倒序,1为正序

2.6、索引

索引能够极大提高查询的效率。类似于MySQL,MongoDB中叶提供了索引支持。在没有索引的时候,MongoDB需要便利整个集合,查询效率很低。
为MongoDB创建索引的命令如下,为age域设置一个递增的索引

#创建索引
#说明:1表示升序创建索引,-1表示降序创建索引。
> db.user.createIndex({'age':1})

3. MongoDB 集群

3.1 单机MongoDB存在的问题

单机MongoDB并不适用于企业场景,原因主要有以下两点:

  • 单点故障:MongoDB一旦发生宕机,则会导致应用的崩溃
  • 海量数据的存储问题:单机无法满足海量数据存储的需求。

为了解决上述的问题,便引入了MongoDB 集群。

3.2 MongoDB 集群的三种形式

  • 主从集群(Master-Slaver):是一种主从副本模式,现在已经弃用。
  • 副本集群(Replica Set):取代主从集群,可以解决单点故障的问题
  • 分片集群(Sharding):可以解决单点故障和海量数据存储的问题。

3.3 副本集群

副本集群有一下特点:

  • 一个集群中包含主节点和副本节点
  • 主节点只能有一个,可以完成数据的读写操作
  • 副本节点可以有多个,只能读取数据
  • 多个节点之间有心跳感应,并进行数据同步
  • 主节点宕机后,会自动从副本节点中选择一个成为主节点。


然而,尽管副本节点解决了单点故障的问题,但是并没有解决海量数据存储的问题。

3.4 分片集群

该模式适合存储海量数据,将数据分成不同的片,分别存储在不同的服务器上,从而实现容量的扩充。

分片集群包含三个重要的结构

  • 分片服务:用于保存数据片
  • 配置服务:当集群启动的时候,会读取分片的信息
  • 路由服务:根据客户端的请求,到配置服务中取选择合适的分片服务,然后将请求转发到对应的分片服务上。

此外,我们发现,一旦某一个分片服务宕机,那么数据就不完整了。因此在实际应用中,通常是结合分片集群和副本集群。对每一个分片服务设立副本集群,从而提高集群的健壮性。

MongoDB通过分片策略决定将数据保存到哪一个分片上。MongoDB有两种分片策略,根据集合字段来指定。

  • 范围指定:根据指定字段的数据按照范围进行划分,根据范围到不同的分片服务器读取数据
  • 数据哈希:根据指定字段进行哈希运算获取分片服务器

如上图所示,可以根据年龄进行分片。可以指定1-35岁的保存在分片1

也可以以id分片,利用哈希

4. Springboot整合MongoDB

Spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作,封装了底层的mongodb-driver。在Springboot中使用MongoDB的步骤如下:

  • 导入依赖
  • 编写配置信息
  • 编写集合实体类
  • 注入MongoTemplate对象,完成CRUD操作

导入依赖

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

编写application.yml

spring:data:mongodb:uri: mongodb://192.168.136.160:27017/test

编写集合对应的实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(value="tb_person")
public class Person {@Idprivate ObjectId id;@Field("myname")private String name;private int age;private String address;
}
  • 只要是MongoDB的集合实体类,都需要添加@Document(value="XXX")注解,在MongoDB中,集合的名称就为XXX
  • 在实体类中,需要指定MongoDB的文档的ID,这个ID由MongoDB自动生成,不会重复。在ID字段上使用@Id指定。ID的类型应为ObjectId
  • 可以通过@Field("myname")来指定保存集合的域的名称,如果不指定,默认就以变量面作为域名

引入MongoTemplate

@Resource
private MongoTemplate mongoTemplate;

下面编写了一个测试类,来以Java代码的方式对MongoDB进行CRUD操作

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MongoApplication.class)
public class MongoTest {@Resourceprivate MongoTemplate mongoTemplate;@Testpublic void testInsert() {// 插入一条数据Person person = new Person();person.setAddress("上海");person.setAge(23);person.setName("Robert");this.mongoTemplate.save(person);}@Testpublic void testFindAll() {// 查询所有数据List<Person> all = this.mongoTemplate.findAll(Person.class);all.forEach(System.out::println);}@Testpublic void testFindByCondition() {// 根据条件查询Criteria criteria = Criteria.where("age").is(23).and("myname").is("Robert");Query query = new Query(criteria);List<Person> people = this.mongoTemplate.find(query, Person.class);people.forEach(System.out::println);}@Testpublic void testFindPage() {int page = 2;int size = 5;// 条件分页Criteria criteria = Criteria.where("age").lt(55);Query query = new Query(criteria);query.skip((page - 1) * size).limit(size).with(Sort.by(Sort.Order.desc("age")));List<Person> people = this.mongoTemplate.find(query, Person.class);people.forEach(System.out::println);}@Testpublic void testUpdate() {Query query = new Query(Criteria.where("id").is("63a431e998e6c17444113fc9"));// updateFirst是更新满足条件的第一个记录// 设置要更新的内容Update update = new Update();update.set("myname", "Jack");this.mongoTemplate.updateFirst(query, update, Person.class);}@Testpublic void testDelete() {// 根据条件删除Query query = new Query(Criteria.where("myname").is("Jack"));this.mongoTemplate.remove(query, Person.class);}
}

【MongoDB入门】相关推荐

  1. mongoDB 入门指南、示例

    http://www.cnblogs.com/hoojo/archive/2011/06/01/2066426.html mongoDB 入门指南.示例 上一篇:简单介绍mongoDB 一.准备工作 ...

  2. mongodb入门的几篇文章

    2019独角兽企业重金招聘Python工程师标准>>> mongoDB 入门指南.示例 比较简洁概要的描述了mongodb中常用的操作. 8天学通MongoDB 从安装,简单的增删改 ...

  3. PyMongo--非关系型数据库mongodb入门(一步一步 版)

    PyMongo--非关系型数据库mongodb入门(一步一步 版) 本文主要内容: 1.简要介绍mongodb 2.Pymongo 3.mongo shell 4.我的mongodb入门之旅 1.简要 ...

  4. MongoDB入门 - 安装教程

    MongoDB是NoSQL分布式文件存储型数据库 1. 官网下载 官网 版本选择&&下载 历史版本 一览表 2. 安装步骤 双击.msi运行程序: 接着按下图所示安装: 慢慢等待,别急 ...

  5. MongoDB入门基础知识

    一.MongoDB介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为web应用提供可扩展的高性能数据存储解决方案. MongoDB是一种可扩展的敏捷NoSQL数据库,其中M ...

  6. 探花交友_第2章-完善个人信息与MongoDB入门

    探花交友_第2章-完善个人信息与MongoDB入门 文章目录 探花交友_第2章-完善个人信息与MongoDB入门 1.完善个人信息 1.1.图片上传 1.1.1.图片存储解决方案 1.1.2.阿里云O ...

  7. MongoDB 入门教程实战学习笔记-31-mongo 聚合查询管道 Aggregation Pipieline

    aggregation 聚合操作处理数据记录并返回计算结果. 聚合操作将多个文档中的值组合在一起, 并且可以对分组数据执行各种操作以返回单个结果. mongodb 提供了三种执行聚合的方法: 聚合管道 ...

  8. 【ReactJs+springBoot项目——租房】第6章:MongoDB入门+SpringBoot整合MongoDB+搭建微聊系统+实现微聊功能

    MongoDB入门 MongoDB的java api的使用 SpringBoot整合MongoDB使用 搭建微聊系统 实现微聊功能 分布式WebSocket解决方案分析 1.MongoDB入门 1.1 ...

  9. php mongodb插入中文,mongodb入门-5插入

    mongodb入门-5插入 对于每一个数据库来说必不可少的是增删改查.先介绍一下增,也就是插入. 对比四个操作,在mongodb中最简单是插入.在mongodb中插入就是使用insret命令.在使用这 ...

  10. mongodb入门-9查询4

    mongodb入门-9查询4 mongodb入门-8查询3 http://www.2cto.com/database/201305/212158.html $elemMatch 匹配内嵌文章中的数据, ...

最新文章

  1. centos 7 lvs 负载均衡搭建部署
  2. Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8
  3. python3 socketserver_Python3中的SocketServer
  4. 130242014045 林承晖 第2次实验
  5. python利用opencv标注bounding box
  6. 前端学习(3017):vue+element今日头条管理--优化封装请求
  7. Windows小工具广告弹窗杀手+源码
  8. Oracle入门第二天(下)——单行函数
  9. c模拟linux进程管理课程设计,操作系统课程设计(三):Linux进程管理
  10. 云呐|RFID资产盘点系统带审批(rfid库存盘点功能)
  11. php解压有密码的压缩包,linux下解压有密码的rar压缩包
  12. 取消GitHub邮箱订阅
  13. 网页在线即时翻译- -
  14. 实时网速显示_实例_python
  15. FigDraw 22. SCI文章中绘图之核密度及山峦图 (ggridges)
  16. HaploMerger2: 从高杂合二倍体基因组组装中重建单倍型
  17. 很好的源码软件列表,有助于学习提高
  18. 远程办公效率打折,怎么办?
  19. 大数据专业学起来会不会很累?
  20. matlab求矩阵的谱半径,【什么是矩阵的谱半径?怎么求?】百度-谱半径

热门文章

  1. libpcap解析pcapng文件
  2. redis实现抢红包功能
  3. open函数和 write函数
  4. 采用SmartQQ 协议可制作聊天机器人
  5. Bootstrap笔记(七) 排版 - 文字篇
  6. thiel熵计算_彼得·泰尔(Peter Thiel)的前参谋长现在有五百亿美元的五角大楼预算
  7. 巧言的杀伤力(ZT)
  8. Python股票分析系列——获得标普500的所有公司股票数据.p6
  9. 大型工业设施的辐射噪声控制方法概论
  10. FMCW雷达测距、测速与测角