【MongoDB入门】
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 开发应用程序使用的就是逻辑结构。
- MongoDB 的文档(document),相当于关系数据库中的一行记录。
- 多个文档组成一个集合(collection),相当于关系数据库的表。
- 多个集合(collection),逻辑上组织在一起,就是数据库(database)。
- 一个 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入门】相关推荐
- mongoDB 入门指南、示例
http://www.cnblogs.com/hoojo/archive/2011/06/01/2066426.html mongoDB 入门指南.示例 上一篇:简单介绍mongoDB 一.准备工作 ...
- mongodb入门的几篇文章
2019独角兽企业重金招聘Python工程师标准>>> mongoDB 入门指南.示例 比较简洁概要的描述了mongodb中常用的操作. 8天学通MongoDB 从安装,简单的增删改 ...
- PyMongo--非关系型数据库mongodb入门(一步一步 版)
PyMongo--非关系型数据库mongodb入门(一步一步 版) 本文主要内容: 1.简要介绍mongodb 2.Pymongo 3.mongo shell 4.我的mongodb入门之旅 1.简要 ...
- MongoDB入门 - 安装教程
MongoDB是NoSQL分布式文件存储型数据库 1. 官网下载 官网 版本选择&&下载 历史版本 一览表 2. 安装步骤 双击.msi运行程序: 接着按下图所示安装: 慢慢等待,别急 ...
- MongoDB入门基础知识
一.MongoDB介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为web应用提供可扩展的高性能数据存储解决方案. MongoDB是一种可扩展的敏捷NoSQL数据库,其中M ...
- 探花交友_第2章-完善个人信息与MongoDB入门
探花交友_第2章-完善个人信息与MongoDB入门 文章目录 探花交友_第2章-完善个人信息与MongoDB入门 1.完善个人信息 1.1.图片上传 1.1.1.图片存储解决方案 1.1.2.阿里云O ...
- MongoDB 入门教程实战学习笔记-31-mongo 聚合查询管道 Aggregation Pipieline
aggregation 聚合操作处理数据记录并返回计算结果. 聚合操作将多个文档中的值组合在一起, 并且可以对分组数据执行各种操作以返回单个结果. mongodb 提供了三种执行聚合的方法: 聚合管道 ...
- 【ReactJs+springBoot项目——租房】第6章:MongoDB入门+SpringBoot整合MongoDB+搭建微聊系统+实现微聊功能
MongoDB入门 MongoDB的java api的使用 SpringBoot整合MongoDB使用 搭建微聊系统 实现微聊功能 分布式WebSocket解决方案分析 1.MongoDB入门 1.1 ...
- php mongodb插入中文,mongodb入门-5插入
mongodb入门-5插入 对于每一个数据库来说必不可少的是增删改查.先介绍一下增,也就是插入. 对比四个操作,在mongodb中最简单是插入.在mongodb中插入就是使用insret命令.在使用这 ...
- mongodb入门-9查询4
mongodb入门-9查询4 mongodb入门-8查询3 http://www.2cto.com/database/201305/212158.html $elemMatch 匹配内嵌文章中的数据, ...
最新文章
- centos 7 lvs 负载均衡搭建部署
- Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8
- python3 socketserver_Python3中的SocketServer
- 130242014045 林承晖 第2次实验
- python利用opencv标注bounding box
- 前端学习(3017):vue+element今日头条管理--优化封装请求
- Windows小工具广告弹窗杀手+源码
- Oracle入门第二天(下)——单行函数
- c模拟linux进程管理课程设计,操作系统课程设计(三):Linux进程管理
- 云呐|RFID资产盘点系统带审批(rfid库存盘点功能)
- php解压有密码的压缩包,linux下解压有密码的rar压缩包
- 取消GitHub邮箱订阅
- 网页在线即时翻译- -
- 实时网速显示_实例_python
- FigDraw 22. SCI文章中绘图之核密度及山峦图 (ggridges)
- HaploMerger2: 从高杂合二倍体基因组组装中重建单倍型
- 很好的源码软件列表,有助于学习提高
- 远程办公效率打折,怎么办?
- 大数据专业学起来会不会很累?
- matlab求矩阵的谱半径,【什么是矩阵的谱半径?怎么求?】百度-谱半径