MongoDB 学习笔记
文档地址:https://docs.mongodb.com/manual/
1、简介
1.1、说明
官方
MongoDB是一个文档数据库
,旨在方便应用开发和扩展。
百度百科
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中功能最丰富,最像关系型数据库的。他支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复杂的数据类型(比如:{"key":"value", "likes":['', '']}
) 。MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
总结:MongoDB 是一个非关系型的文档数据库
1.2、历史
- 2009年2月,MongoDB 数据库首次在数据库领域亮相,打破了关系型数据库一统天下的局面;
- 2010年8月,MongoDB 1.6 发布。这个版本最大的一个功能就是 Sharding,自动分片
- 2014年12月,MongoDB 3.0 发布。由于收购了 WiredTiger 存储引擎,大幅提升了 MongoDB 的写入性能;
- 2015年12月,3.2 版本发布,开始支持了关系型数据库的核心功能:关联。你可以一次同时查询多个 MongoDB 的集合。
- 2016年,MongoDB 推出 Atlas,在 AWS、 Azure 和 GCP 上的 MongoDB 托管服务;
- 2017年10月,MongoDB 成功在纳斯达克敲钟,成为 26 年来第一家以数据库产品为主要业务的上市公司。
- 2018年6月,MongoDB 4.0 发布推出 ACID 事务支持,成为第一个支持强事务的 NoSQL 数据库;
- 2018年–至今,MongoDB 已经从一个在数据库领域籍籍无名的“小透明”,变成了话题度和热度都很高的“流量”数据库。
2、特点
- 面向集合存储,易存储对象类型的数据
- 支持查询,以及动态查询
- 支持 RUBY,PYTHON,JAVA,C++,PHP,C# 等多种语言
- 文件存储格式为 BSON(一种 JSON 的扩展)
- 支持复制、故障恢复和分片
- 支持单条记录的事务(强一致性,达到了 mysql 级别)
- 支持索引、聚合、关联d
2.1、应用场景
- 游戏应用:使用云数据库 MongoDB 作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便查询与更新。
- 物流应用:使用云数据库 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以云数据库 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。
- 社交应用:使用云数据库 MongoDB 存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且,云数据库MongoDB 非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并且在写入和读取方面都相对较快。
- 视频直播:使用云数据库 MongoDB 存储用户信息、礼物信息等。
- 大数据应用:使用云数据库 MongoDB 作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。
3、安装
3.1、传统方式
1、下载 MongoDB:https://www.mongodb.com/try/download/community
2、将安装包上传到 linux 系统,并进行解压
tar -zxvf mongodb-linux-x86_64-rhel70-5.0.14.tgz
3、查看安装目录
bin目录:用来存放启动 mongoDB 的服务以及客户端连接的脚本文件等
4、启动 MongoDB 服务
./mongod --port=27017 --dbpath=../data --logpath=../logs/mongo.log
--port:指定服务监听端口号,默认为 27017
--dbpath:指定 mongodb 数据存放目录,启动时要求目录必须存在
--logpath: 指定 mongodb 日志文件的存放位置
注意:由于已经指定日志文件的存放目录,因此启动时终端不显示任何日志
5、客户端连接
./mongo --port=27017
3.2、Docker方式
1、拉取 mongodb 镜像
docker pull mongo:5.0.5
2、运行 mongo 镜像
docker run -d --name mongo -p 27017:27017 mongo:5.0.5
3、进入 mongo 容器
docker exec -it d3c7b4037e4b bash
4、在容器内部启动 mongo 客户端
mongo
5、退出 mongo 客户端
exit
4、核心概念
4.1、库
MongoDB 中的库就类似于传统关系型数据库中库的概念,用来通过不同库隔离不同的应用数据。MongoDB 中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为"test
",数据库存储在启动时指定的 data 目录中。
4.2、集合
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中 表
的概念。
集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
4.3、文档
文档集合中的一条条记录,是一组键值 key-value
对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
一个简单的文档例子如下:
{"site":"www.baidu.com", "name":"百度"}
4.4、关系总结
RDBMS | MongoDB |
---|---|
数据库 | 数据库 |
表
| 集合 |
行 | 文档 |
列 | 字段 |
5、基本操作
5.1、库
清除屏幕内容
cls
查看所有库
show databases;
show dbs;
admin
: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户就会自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。- **
local
:**这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。 - **
config
:**当 Mongo 用于分片设置时,config 数据库在内部使用,用于保存分片的相关信息。
创建库
use 库名
注意:use 代表创建并使用库,当库中没有数据时默认不显示这个库
查看当前所在的库
db
删除数据库
默认删除当前选中的库
db.dropDatabase();
5.2、集合
创建集合
db.createCollection('集合名称', [options])
options 可以是如下参数:
字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
size | 数值 | (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
注意:当集合不存在时,向集合中插入文档也会自动创建该集合。
查看库中的所有集合
show collections;
show tables;
删除集合
db.集合名称.drop();
5.3、文档
参考文档:https://docs.mongodb.com/manual/reference/method/
插入文档
单条文档:
db.集合名称.insert({name:'编程',age:23,bir:"2022-12-07"});
多条文档:
db.集合名称.insert(
[ <document 1> , <document 2>, ... ],
{
writeConcern: 1, # 写入策略,默认为 1,即要求确认写操作,0 是不要求。
ordered: true # 指定是否按顺序写入,默认为 true,表示按顺序写入。
}
)
# ---------------------------------------------------------
db.集合名称.insert([
{"name":"不良人","age":23,"bir":"2012-12-12"},
{"name":"小黑","age":25,"bir":"2012-12-12"}
]);
注意:在 mongodb 中每个文档都会有一个 _id
作为唯一标识,_id
默认会自动生成,如果手动指定将使用手动指定的值作为 _id
的值。
脚本方式:
for(let i=0;i<100;i++){
db.users.insert({"_id":i,"name":"编程不良人_"+i,"age":23});
}
查询所有文档
db.集合名称.find();
删除文档
db.集合名称.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
- query:(可选)删除文档的条件。
- justOne:(可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
- writeConcern:(可选)抛出异常的级别。
更新文档
db.集合名称.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
);
- query:update 的查询条件,类似 sql update 查询内
where
后面的。 - update:update 的对象和一些更新的操作符(如
$
、$inc...
)等,也可以理解为 sql update 查询内set
后面的。 - upsert:(可选)这个参数的意思是,如果不存在 update 的记录,是否插入新数据,true 为插入,默认是 false,不插入。
- multi:(可选)mongodb 默认是 false,只更新找到的第一条记录,如果这个参数为 true,就把按条件查出来的多条记录全部更新。
- writeConcern:(可选)抛出异常的级别。
db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()})
# 这个更新是将符合条件的全部更新成后面的文档,相当于先删除再更新
db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming"}})
# 保留原来数据更新,但是只更新符合条件的第一条数据
db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true})
# 保留原来数据更新,更新符合条件的所有数据
db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true,upsert:true})
# 保留原来数据更新,更新符合条件的所有数据,没有条件符合时插入数据
6、文档查询
MongoDB 查询文档使用 find()
方法。find()
方法以非结构化的方式来显示所有文档。
语法
db.集合名称.find(query, projection)
- query:(可选)使用查询操作符指定查询条件
- projection:(可选)使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty()
方法,语法格式如下:
db.集合名称.find().pretty()
注意:pretty()
方法以格式化的方式来显示文档,并且是超过一定长度的文档才会进行格式化。
对比语法
如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:
AND
db.集合名称.find({key1:value1, key2:value2,...}).pretty()
类似于 WHERE 语句:WHERE key1=value1 AND key2=value2
OR
MongoDB 中 OR
条件语句使用了关键字 $or
**,**语法格式如下:
> db.集合名称.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
类似于 WHERE 语句:WHERE key1=value1 or key2=value2
AND 和 OR 联合
类似 SQL 语句为:where age >50 AND (name = '编程' OR name = 'MongoDB')
db.集合名称.find({"age": {$gt:50}, $or: [{"name": "编程"},{"name": "MongoDB"}]}).pretty();
数组中查询
$size 按照数组长度查询
db.users.find({likes:{$size:3}});
模糊查询
类似 SQL 中 where name like '%name%'
db.users.find({name:/程/});
注意:在 mongoDB 中使用正则表达式可以实现近似模糊查询的功能
排序
db.集合名称.find().sort({name:1,age:1})
# 1 表示升序,-1 表示降序
类似 SQL 语句:order by name,age
分页
db.集合名称.find().sort({条件}).skip(start).limit(rows);
类似于 SQL 语句:limit start,rows
总条数
db.集合名称.count();
db.集合名称.find({"name":"编程"}).count();
类似于 SQL 语句:select count(id) from ....
去重
db.集合名称.distinct('字段')
类似于 SQL 语句:select distinct name from ....
指定返回字段
db.集合名称.find({条件},{name:1, age:1})
7、$type
说明
$type
操作符是基于 BSON 类型来检索集合中匹配的数据类型,并返回结果。
MongoDB 中可以使用的类型如下表所示:
注意:在 MongoDB 中,只要我们放入的是数字,那么默认就是 Double 类型。
使用
db.col.insert({
title: 'PHP 教程',
description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
by: '编程不良人',
url: 'http://www.baizhiedu.xin',
tags: ['php'],
likes: 200
});
db.col.insert({
title: 'Java 教程',
description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
by: '编程不良人',
url: 'http://www.baizhiedu.xin',
tags: ['java'],
likes: 550
});
db.col.insert({
title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '编程不良人',
url: 'http://www.baizhiedu.xin',
tags: ['mongodb'],
likes: 100
});
db.col.insert({
title: 2233,
description: '2233 是一个 B站的',
by: '编程不良人',
url: 'http://www.baizhiedu.xin',
tags: ['2233'],
likes: 100
});
如果想获取 “col” 集合中 title 为 String 类型的数据,可以使用以下命令:
db.col.find({"title" : {$type : 2}}).pretty();
或
db.col.find({"title" : {$type : 'string'}}).pretty();
如果想获取 “col” 集合中 tags 为 Array 类型的数据,可以使用以下命令:
db.col.find({"tags" : {$type : 4}}).pretty();
或
db.col.find({"tags" : {$type : 'array'}}).pretty();
8、索引
https://docs.mongodb.com/manual/indexes/
说明
索引通常能够极大的提高查询效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,一次查询可能要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
原理
从根本上说,MongoDB 中的索引类似于其他数据库系统中的索引。MongoDB 在集合层面上定义了索引, 并支持在 MongoDB 集合中的文档的任何字段或子字段上建立索引。
操作
1、创建索引
db.集合名称.createIndex(keys, options)
db.集合名称.createIndex({"title":1, "description":-1})
说明:语法中 Key 值为你要创建的索引字段,1
为指定按升序创建索引,如果你想按降序来创建索引则指定为 -1
即可。
createIndex( ) 接收可选参数,可选参数列表如下:
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false。 |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为 true 的话,在索引字段中不会查询出不包含对应字段的文档。默认值为 false。 |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL 设定,设定索引的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于 mongod 创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language。 |
2、查看集合索引
db.集合名称.getIndexes()
3、查看集合索引大小
db.集合名称.totalIndexSize()
4、删除集合中的所有索引(不会删除 _id
的索引)
db.集合名称.dropIndexes()
5、删除集合中的指定索引
db.集合名称.dropIndex("索引名称")
联合索引
说明:一个索引的值是由多个 key 进行维护的索引称之为联合索引。
db.集合名称.createIndex({"title":1, "description":-1})
注意:MongoDB 中联合索引和传统关系型数据库一致都是最左前缀原则。
9、聚合
说明
MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似 SQL 语句中的 count(*)
。
使用
db.tests.insert([
{
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
}
]);
现在我们可以通过以上集合,计算每个作者所写的文章数,使用 aggregate()
计算结果如下:
db.集合名称.aggregate([{$group : {_id : "$by_user", 'sum_by_user': {$sum : 1}}}])
常见聚合表达式
10、MongoDB 整合 SpringBoot
说明:这里主要以 springboot 应用为基础进行整合开发。
如果使用传统方式安装 MongoDB,那么默认是没有开启远程调用权限的;而如果是通过 Docker 方式安装 MongoDB,则默认会开启远程调用权限。
环境搭建
引入依赖
<!--mongo client 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
编写配置
# mongodb 没有开启任何安全协议
# mongodb(协议)://121.5.167.13(主机):27017(端口)/baizhi(库名)
spring.data.mongodb.uri=mongodb://1.117.115.99:27017/test
# mongodb 开启用户名密码校验
#spring.data.mongodb.host=1.117.115.99
#spring.data.mongodb.port=27017
#spring.data.mongodb.database=test
#spring.data.mongodb.username=root
#spring.data.mongodb.password=root
集合操作
创建集合
// 1.创建集合
@Test
public void testCreateCollection() {
// 判断当前集合是否存在
boolean exists = mongoTemplate.collectionExists("products");
if (!exists) {
// 创建集合
mongoTemplate.createCollection("products");
}
}
注意:创建集合不能存在,如果存在则会报错
删除集合
// 2.删除集合操作
@Test
public void testDropCollection() {
mongoTemplate.dropCollection("products");
}
相关注解
@Document
- 修饰范围:用在类上
- 作用:用来映射这个类的一个对象作为 mongo 中的一条文档数据
- 属性:(
value、collection
)用来指定操作的集合名称
@Id
- 修饰范围:用在成员变量、方法上
- 作用: 用来将成员变量的值映射为文档 _id 的值
@Field
- 修饰范围:用在成员变量、方法上
- 作用:用来将成员变量以及值映射为文档中一个 key、value 对
- 属性:(
name、value
)用来指定在文档中 key 的名称,默认为成员变量名
@Transient
- 修饰范围:用在成员变量、方法上
- 作用:用来指定该成员变量,不参与文档的序列化
@Document("users") // 这个类的实例就代表 mongo 中的一条文档
public class User {
@Id // 用来将这个类的 "id" 映射为文档中的 "_id"
private Integer id;
@Field("username")
private String name;
@Field
private Double salary;
@Field
private Date birthday;
@Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + ", salary=" + salary + ", birthday=" + birthday + '}';
}
public User() {
}
public User(Integer id, String name, Double salary, Date birtday) {
this.id = id;
this.name = name;
this.salary = salary;
this.birthday = birtday;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
文档操作
添加
/**
* 文档的添加操作
*/
@Test
public void testSaveOrUpdate() {
//User user = new User(2, "剑神", 2500.1, new Date());
// save 方法在 _id 存在时更新数据
//mongoTemplate.save(user);
// insert 方法在 _id 存在时主键冲突
//mongoTemplate.insert(user);
List<User> users = Arrays.asList(new User(6, "姜泥", 2800.1, new Date()), new User(7, "红薯", 2800.1, new Date()), new User(8, "张小五", 2800.1, new Date()));
// 参数1:批量数据,参数2:放入哪个集合
mongoTemplate.insert(users, User.class);
}
- insert:插入重复数据时,
insert
方法会报DuplicateKeyException
异常,提示主键重复;而save
方法对已存在的数据会进行更新。 - save:在进行批处理操作时,
insert
方法可以一次性插入整个数据,效率较高;而save
方法则需要遍历所有数据来完成插入或更新,效率较低。
查询
/**
* 文档的查询操作
*/
@Test
public void testFind() {
// 1.查询所有数据,参数表示将文档转换成哪个类型的对象
mongoTemplate.findAll(User.class);
// 也可以指定从哪个集合进行查询
mongoTemplate.findAll(User.class, "users");
// 2.基于 id 查询一个
mongoTemplate.findById(1, User.class);
// 3.条件查询 参数1:查询条件,参数2:返回类型
mongoTemplate.find(new Query(), User.class);
// 4.等值查询
mongoTemplate.find(Query.query(Criteria.where("username").is("张小五")), User.class);
mongoTemplate.find(Query.query(Criteria.where("name").is("张小五")), User.class);
// 5.> < >= <= 查询
mongoTemplate.find(Query.query(Criteria.where("salary").lte(2400.1)), User.class);
// 6.and 查询
mongoTemplate.find(Query.query(Criteria.where("name").is("徐凤年").and("salary").is(2300.1)), User.class);
// 7.or 查询
Criteria criteria = new Criteria();
criteria.orOperator(Criteria.where("name").is("徐凤年"), Criteria.where("name").is("剑神"));
mongoTemplate.find(Query.query(criteria), User.class);
// 8. and 和 or 连用
mongoTemplate.find(Query.query(Criteria.where("salary").is(2800.1).orOperator(Criteria.where("name").is("张小五"))), User.class);
// 9.排序
Query querySort = new Query();
querySort.with(Sort.by(Sort.Order.asc("salary")));
mongoTemplate.find(querySort, User.class);
// 10.分页查询
Query querySortPage = new Query();
// skip表示从第几行开始,limit表示每页显示多少条数据
querySortPage.with(Sort.by(Sort.Order.asc("salary"))).skip(4).limit(2);
mongoTemplate.find(querySortPage, User.class);
// 11.查询总条数
long count = mongoTemplate.count(Query.query(Criteria.where("name").is("徐凤年")), User.class);
System.out.println("count = " + count);
// 12.去重 distinct
// 参数1:查询条件,参数2:去重字段,参数3:操作集合,参数4:返回类型
List<Double> salary = mongoTemplate.findDistinct(new Query(), "salary", User.class, Double.class);
System.out.println("salary = " + salary);
// 13.使用 json 字符串方式进行查询
BasicQuery basicQuery = new BasicQuery("{$or:[{name:'剑神'}, {name:'徐凤年'}]}");
List<User> users = mongoTemplate.find(basicQuery, User.class);
users.forEach(System.out::println);
}
更新
/**
* 文档的更新操作
*/
@Test
public void testUpdate() {
Update update = new Update();
//update.setOnInsert("_id", 10);
update.set("salary", 4001.1);
/**
* 只更新符合条件的第一条数据
*/
mongoTemplate.updateFirst(Query.query(Criteria.where("name").is("徐凤年")), update, User.class);
/**
* 符合条件的多条数据都更新
*/
mongoTemplate.updateMulti(Query.query(Criteria.where("salary").is(2800.1)), update, User.class);
/**
* 没有符合条件则插入数据
*/
UpdateResult updateResult = mongoTemplate.upsert(Query.query(Criteria.where("salary").is(2800.1)), update, User.class);
System.out.println("本次修改的记录数:" + updateResult.getModifiedCount());
System.out.println("本次匹配的记录数:" + updateResult.getMatchedCount());
System.out.println("如果采用自动生成的_id,那么生成的_id是:" + updateResult.getUpsertedId());
}
删除
/**
* 文档的删除操作
*/
@Test
public void testRemove() {
// 删除文档的所有数据
//mongoTemplate.remove(new Query(), User.class);
// 按条件进行删除数据
mongoTemplate.remove(Query.query(Criteria.where("name").is("张小五")), User.class);
}
11、副本集
https://docs.mongodb.com/manual/replication/
MongoDB 副本集(Replica Set)是具有自动故障恢复功能的主从集群,由一个 Primary 节点和多个 Secondary 节点组成。副本集没有固定的主节点
,当主节点发生故障时,整个集群会选举一个主节点为系统提供服务以保证系统的高可用。
Automatic Failover
自动故障转移机制:当主节点未与集合中的其他成员通信并且超过配置的超时时间(默认为 10 秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点。集群将尝试完成新主节点的选举并恢复正常操作。
注意:当 mongodb 副本集架构中只剩下一个节点时,整个节点是不可用的。
搭建副本集
1、创建数据目录
cd /opt/mongodb/bin/
# 在安装目录中创建
mkdir -p ../repl/data1
mkdir -p ../repl/data2
mkdir -p ../repl/data3
2、搭建副本集
./mongod --port 27017 --dbpath ../repl/data1 --bind_ip 0.0.0.0 --replSet myreplace/[1.117.115.99:27018,1.117.115.99:27019]
./mongod --port 27018 --dbpath ../repl/data2 --bind_ip 0.0.0.0 --replSet myreplace/[1.117.115.99:27019,1.117.115.99:27017]
./mongod --port 27019 --dbpath ../repl/data3 --bind_ip 0.0.0.0 --replSet myreplace/[1.117.115.99:27017,1.117.115.99:27018]
注意:--replSet myreplace
副本集名称/集群中其他节点的主机和端口
3、配置副本集
- 先连接任意节点
cd /opt/mongodb/bin/
./mongo --port 27017
- 初始化副本集:
var config = {
_id:"myreplace",
members:[
{_id:0,host:"1.117.115.99:27017"},
{_id:1,host:"1.117.115.99:27018"},
{_id:2,host:"1.117.115.99:27019"}]
}
rs.initiate(config); # 初始化配置
- 设置客户端临时可以访问
rs.secondaryOk();
客户端连接副本集说明
application.properties 配置如下:
# mongo replica set
spring.data.mongodb.uri=mongodb://1.117.115.99:27017,1.117.115.99:27018,1.117.115.99:27019/test?replicaSet=myreplace
12、分片集群
https://docs.mongodb.com/manual/sharding/
分片(sharding)是指将数据进行拆分,将其分散到不同机器的过程,有时也用分区(partitioning)来表示这个概念,将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。
分片的目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用运行。
MongoDB 支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。MongoDB 分片的基本思想就是将集合拆分成多个块,这些块分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程(mongos 进程),这个路由器知道所有数据的存放位置,应用只需要直接与 mongos 进行交互即可。mongos 自动将请求转发到相应的片上获取数据,从应用角度来看,分不分片没有什么区别。
- Shard:用于存储实际的数据块,实际生产环境中一个 shard server 角色可由几台机器组个一个 replica set 承担,防止主机单点故障
- Config Server:mongod 实例:存储了整个 ClusterMetadata。
- Query Routers:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
- Shard Key:片键,设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key),片键的选取很重要,片键的选取决定了数据散列是否均匀。