MongoDB学习笔记
文章目录
- 1 MongoDB简介
- 2 MongoDB环境搭建
- 3 核心概念
- 4 MongoDB基本操作
- 5 文档之间的关系
- 6 MongoDB索引
- 7 Java操作MongoDB
- 8 SpringBoot整合MongoDB
- 9 MongoDB主从集群
- 10 MongoDB分片集群
1 MongoDB简介
1.1 数据库简介
。数据库是按照数据结构来组织、存储和管理数据的仓库
。我们的程序都是在内存中运行的,一旦程序运行结束或者计算机断电,程序运行中的数据都会丢失
。所以我们就需要将一些程序运行的数据持久化到硬盘之中,以确保数据的安全性。而数据库就是数据持久化的最佳选择。
。说白了,数据库就是存储数据的仓库
1.2 数据库分类
数据库主要分为两种:
—关系型数据库(RDBMS)
。MySQL、Oracle、DB2、SQL Server…
—非关系型数据库(No SQL:not only SQL) SQL:关系型查询语言
。MongoDB、Redis…
。键值对数据库
。文档数据库MongoDB
1.3 MongoDB简介
。MongoDB是为了快速开发互联网Web应用而设计的数据库系统
关系型数据库,开发之前,要花很长时间进行表结构设计,
但非关系型数据库,不用先进行完善的表结构设计,可以边开发边设计,可以以后有需要,再临时增加,所以更快
。MongoDB的设计目标是极简、灵活、作为Web应用栈的一部分
。MongoDB的数据模型是面向文档的,所谓文档是一种类似于JSON的结构,
简单理解MongoDB这个数据库中存的是各种各样的JSON。
mongodb里面存的是json格式的数据 bson
MongoDB是介于关系数据库和非关系数据库之间的产品,是非关系型数据库中最像关系型数据库的。
几乎可以实现类似关系型数据库单表查询的大部分功能,而且还支持对数据建立索引。
总结: MongoDB是一个非关系型文档数据库
2018年–至今,MongoDB已经从数据库领域籍籍无名的“小透明”变成了话题度和热度都很高的“流量”数据库
1.4 MongoDB特点
1.4.1 非结构化数据
MongoDB是弱结构化的数据,NoSQL
1.4.2 性能比较
从数据存储原理来看,更倾向于将mongodb归类为硬盘数据库,但是使用了mmap作为加速的手段而已。
Mongo使用的内存映射技术, 写入数据时候只要在内存里完成就可以返回给应用程序,这样并发量自然就很高。
而保存到硬体的操作则在后台异步完成。
性能比较: Redis > MongoDB > MySQL / Oralce
mongodb对数据的操作大部分都在内存中。但mongodb并不是单纯的内存数据库。甚至个人认为不属于内存数据库。
相反,redis就是一个不折不扣的内存数据库了,
mysql一个不折不扣的硬盘数据库。
我们对比下:
1.redis所有数据都是放在内存中的,持久化是使用RDB方式或者aof方式。
2.mongodb的所有数据实际上是存放在硬盘的,所有要操作的数据通过mmap的方式映射到内存某个区域内。
然后,mongodb就在这块区域里面进行数据修改,避免了零碎的硬盘操作。
至于mmap上的内容flush到硬盘就是操作系统的事情了,所以,如果,mongodb在内存中修改了数据,然后,mmap数据flush到硬盘之前,系统当机了,就会丢失数据了。
3.mysql,无论数据还是索引都存放在硬盘中。到要使用的时候才交换到内存中。能够处理远超过内存总量的数据。
1.5 应用场景
1.5.1 关系型数据库应用场景
关系型数据库适合存储结构化数据,如用户的帐号、地址:
1.这些数据通常需要做结构化查询,比如join,这时候,关系型数据库就要胜出一筹
2.这些数据的规模、增长的速度通常是可以预期的
3.事务性、一致性
1.5.2 非关系型数据库应用场景
NoSQL适合存储非结构化数据,如文章、评论:
1.这些数据通常用于模糊处理,如全文搜索、机器学习
2.这些数据是海量的,而且增长的速度是难以预期的,
3.根据数据的特点,NoSQL数据库通常具有无限(至少接近)伸缩性
4.按key获取数据效率很高,但是对join或其他结构化查询的支持就比较差
1.5.3 MongoDB应用场景
1.表结构不明确且数据不断变大
MongoDB是非结构化文档数据库,扩展字段很容易且不会影响原有数据。内容管理或者博客平台等,例如圈子系统,存储用户评论之类的。
2.更高的写入负载
MongoDB侧重高数据写入的性能,而非事务安全,适合业务系统中有大量“低价值”数据的场景。本身存的就是json格式数据。例如做日志系统。
3.数据量很大或者将来会变得很大
Mysql单表数据量达到5-10G时会出现明细的性能降级,需要做数据的水平和垂直拆分、库的拆分完成扩展,MongoDB内建了sharding、很多数据分片的特性,容易水平扩展,比较好的适应大数据量增长的需求。
4.高可用性
自带高可用,自动主从切换(副本集)
不适用的场景
1.MongoDB不支持事务操作,需要用到事务的应用建议不用MongoDB。
2.MongoDB目前不支持join操作,需要复杂查询的应用也不建议使用MongoDB。
具体来说:
1.游戏应用:使用云数据库MongoDB作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便查询和更新;
2.物流应用:使用云数据库MongoDB存储订单信息,订单状态在运送过程中不断更新,以云数据库MongoDB以内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷一目了然。
3.社交应用:使用云数据库MongoDB存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且,云数据库MongoDB非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并且在写入和读取方面都相对较快。
4.视频直播:使用云数据库MongoDB存储用户信息,礼物信息等。
5.大数据应用:使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态
2 MongoDB环境搭建
2.1 MongoDB下载
。下载地址: https://www.mongodb.org/dl/win32/
。MongoDB的版本偶数版本为稳定版,奇数版本为开发版
。MongoDB对于32位系统支持不佳,所以,3.2版本以后没有再对32位系统的支持
下载后,如图所示:
2.2 MongoDB安装
双击MongoDB安装包即可开始MongoDB的安装:
(1)点击Next
(2)选择Custom 选择Custom用于自定义安装MongoDB。
(3)自定义安装路径 自定义安装路径时最好不要选择默认的C盘,而是安装到其他盘,免得影响电脑运行速度。
(4)安装服务选项保持默认 这一步很关键,是选择是否将MongoDB注册到Windows服务,需要选择默认选项,不要自己修改,
重要的话再说三遍: 不要自己修改!!! 不要自己修改!!! 不要自己修改!!!
这样在安装时就会自动将MongoDB安装到Windows系统服务中,每次使用MongoDB就不需要再单独开启服务了。
在网上有的教程中说这里不要勾选安装MongoDB为服务,后面再自己配置,一是操作过程很繁琐,
而是还容易出错、不能成功,因此就不要瞎折腾了,直接这里勾选安装服务更简单。
(5)取消勾选Compass 因为后面我们选择Robo 3T作为可视化工具,因此就不安装Compass了。
(6)点击开始安装 点击开始安装等待安装结束即可。
(7)在按上述步骤安装成功MongoDB之后,就可以使用MongoDB了,默认已经将其注册到了系统服务中并开启服务,如下:
(8) 此时即可访问http://localhost:27017/,如果看到如下页面,即可验证安装和开启服务成功:
如果不需要使用MongoDB服务,既可以在服务管理窗口中手动关闭MongoDB服务即可,
或者以管理员身份打开CMD,运行net stop mongodb
即可关闭服务。
下次要再开启服务,可以在服务管理窗口中手动开启,
也可以在以管理员身份打开的CMD中执行net start mongodb
即可。
2.3 MongoDB配置
说明:如果3.2安装选择了设置为系统服务,则3.3MongoDB配置就不用配置了。
2.3.1 配置环境变量
pah= D:\01program_soft\02install_after\mongodb\bin
如图所示:
判断MongoDB是否安装成功:
输入命令行: mongod
如图所示:
出现上面的界面,就说明MongoDB安装配置成功了。
2.3.2 启动MongoDB
–在C盘根目录
–创建一个文件夹data
–在data中创建一个文件夹db
–打开cmd命令行窗口,输入mongod命令
非C盘根目录情况: mongod -dbpath 数据库路径 --port 端口号
出现waiting for connections on port 27017 代表启动成功
--窗口不能关闭,关闭窗口就关闭了mongoDB数据库
--另开一个命令行窗口,输入"mongo"回车
出现commecting to:test 代表连接成功 出现>
如图所示:
-数据库(database)
–数据库的服务器
–服务器用来保存数据
–mongod用来启动服务器
–数据库的客户端
–客户端用来操作数据进行增删改查的操作
–mongo用来启动客户端
2.3.3 设置为系统服务
--将mongodb设置为系统服务,可以自动在后台启动,不需要每次都手动启动
1.创建目录 /data/log
2.创建配置文件
在目录D:\01program_soft\02install_after\mongodb下添加配置文件mongod.cfg
mongod.cfg内容:
systemLog:
destination: file
path: c:\data\log\mongod.log
storage:
dbPath: c:\data\db
如果所示:
3.以管理员身份,打开命令行窗口
4.执行如下命令:(命令作业是设置为系统服务)
sc.exe create MongoDB binPath= "“D:\01program_soft\02install_after\mongodb\bin\mongod.exe” --service –
config=“D:\01program_soft\02install_after\mongodb\mongod.cfg”" DisplayName= “MongoDB” start= “auto”
5.启动mongodb服务
6.如果启动失败,证明上面的操作失误
在控制台输入 sc delete MongoDB 删除之前配置的服务
然后从第一步再来一次
2.4 Robo 3T的安装
官方下载地址:https://robomongo.org/download
直接双击安装包即可开始安装:
(1)点击下一步
(2)点击我接受
(3)自定义安装路径 和MongoDB一样,自定义安装路径时也最好不要选择默认的C盘,而是安装到其他盘。
(4)开始安装
(5)点击完成安装
点击完成即可完成安装并打开Robo 3T软件。
2.5 MongoDB连接
打开Robot 3T,新建一个连接:
Name:连接名
Address:MongoDB服务端的连接地址 端口号默认:27017
点击“test”,测试是否能连接成功。
测试成功后,点击“save”按钮。
连接成功后,操作界面如下:
3 核心概念
3个概念:
3.1 数据库 database
MongoDB中的库就类似于传统关系型数据库中库的概念,用来通过不同的库隔离不同应用数据。MongoDB中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为“test”,数据库存储在启动指定的data目录中。
3.2 集合 collection
集合就是MongoDB文档组,类似于RDBMS(关系型数据库管理系统)中的表的概念。
集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
3.3 文档 document
文档是集合中一条一条的记录,是一组键值(key-value)对,(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点。
一个简单的文档例子如下:
{"company":"信必优","name":"汤观林"}
—在MongoDB中,数据库和集合都不需要手动创建,
当我们创建文档时,如果文档所在的集合或者数据库不存在会自动创建数据库和集合
3.4 关系总结
RDBMS 关系型数据库 | MongoDB文档数据库 |
---|---|
数据库 | 数据库 |
表
| 集合 |
行 | 文档 |
列 | 字段 |
4 MongoDB基本操作
4.1 基本指令
show databases 显示当前的所有数据库 show dbs
use test 进入到指定的数据库中
db 当前所处的数据库
show collections 显示数据库中所有的集合
数据库的CRUD(增删改查)的操作
4.2 插入文档
db: 代表当前数据库hello
stus: 代表当前集合collections
4.2.1 插入语法
db.stus.insert() 向集合中插入一个或多个文档
—当我们向集合中插入文档时,如果没有给文档指定 _id属性,则数据库会自动为文档添加 _id
该属性用来作为文档的唯一标识
— _id我们可以自己指定,如果我们指定了数据库就不会再添加了,如果自己指定 _id,也必须确保唯一性
db.stus.insertOne() 向集合中插入一个文档对象
db.stus.insertMany() 向集合中插入多个文档对象
4.2.2 插入1个文档
例1: 向test数据库中的stus集合中插入一个新的学生对象
{“name”:“wangwu”,“age”:“20”,“gender”:“男”,“phone”:“18680314250”}
语句:
db.stus.insert({"name":"wangwu","age":"20","gender":"男","phone":"18680314250"});
运行结果:
{"_id" : ObjectId("61b4def1f25893b6624b2844"),"name" : "wangwu","age" : "20","gender" : "男","phone" : "18680314250"}
4.2.3 插入多个文档
例2:向集合中插入多个文档对象
语句:
db.stus.insert([
{"name":"沙和尚","age":"38","gender":"男"},
{"name":"白骨精","age":"16","gender":"女"},
{"name":"蜘蛛精","age":"14","gender":"女"}
]);
运行结果:
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "38","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e3"),"name" : "白骨精","age" : "16","gender" : "女"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e4"),"name" : "蜘蛛精","age" : "14","gender" : "女"}
4.3 查询文档
4.3.1 查询语法
db.stus.find() 查询集合中所有符合条件的文档
—find() 用来查询集合中所有符合条件的文档
db.stus.find()[0] 返回的是数组 db.stus.find()[0].name
—find() 可以接收一个对象作为条件参数
{} 表示查询集合中所有的文档
{“属性”:“值”} 查询属性是指定值的文档
{“属性1”:“值1”,“属性2”:“值2”} 查询属性1为值1,且属性2为值2的文档
db.stus.findOne() 查询集合中符合条件的第1个文档
db.stus.findOne().name 返回的是对象
db.stus.find().count() 查询所有结果的数量
4.3.2 查询所有文档
例1:查询集合stus中所有的文档 ----查询所有文档
语句: 返回的是数组
db.stus.find() 或 db.stus.find({})
db.stus.find()[1]
运行结果:
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "38","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e3"),"name" : "白骨精","age" : "16","gender" : "女"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e4"),"name" : "蜘蛛精","age" : "14","gender" : "女"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "38","gender" : "男"}
4.3.3 单条件查询
例2:查询name为“沙和尚”的文档 ----单条件查询
语句:
db.stus.find({"name":"沙和尚"});
运行结果:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "29","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "38","gender" : "男"}
4.3.4 多条件查询
例3:查询 name为“沙和尚”,且age为29的文档 ----多条件查询
语句:
db.stus.find({"name":"沙和尚","age":"29"})
运行结果:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "29","gender" : "男"}
4.3.5 findOne()
例4:查询name为“沙和尚”的第1个文档
语句:返回的是对象
db.stus.findOne({"name":"沙和尚"});
db.stus.findOne({"name":"沙和尚"}).name;
运行结果:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "29","gender" : "男"}
沙和尚
4.3.6 find().count()
例5:查询所有文档的数量
语句:
db.stus.find().count();
运行结果:
8
4.4 修改文档
4.4.1 修改语法
db.stus.update(查询条件,新对象) ---- 替换文档
db.stus.update({“属性1”:“值1”},{“属性2”:“值2”})
—update()默认情况下会使用新对象替换旧的对象
—如果需要修改指定的属性,而不是替换需要使用“修改操作符”来完成修改
$set: 可以用来修改文档中的指定属性
db.stus.update({“属性1”:“值1”},{$set:{“属性2”:“值2”}}) 修改文档
update() 默认只会修改一个,修改多个要用updateMany()
db.stus.updateOne() 只修改一个文档
db.stus.updateMany() 修改多个文档
4.4.2 替换update
注意:直接用update, 新对象会直接替换旧对象数据,而不是修改,修改要用 $set:
db.stus.update({"name":"wangwu"},{"age":"22"});
运行结果:
{
"_id" : ObjectId("61b4def1f25893b6624b2844"),
"age" : "22"
}
4.4.3 修改$set
例:将name为蜘蛛精的文档对象的age改为15岁
语法: update() 默认情况下只会修改一个文档
db.stus.update(
{"name":"蜘蛛精"},
{$set:{"age":"15"}}
);
运行结果:
{
"_id" : ObjectId("61b5884137ce3c0fe93e33e4"),
"name" : "蜘蛛精",
"age" : "15",
"gender" : "女"
}
4.4.4 修改多个文档
说明:修改多个要用updateMany()
例:将name为沙和尚的文档对象的age都修改为19
语法:
db.stus.updateMany(
{"name":"沙和尚"},
{$set:{"age":"19"}}
);
运行结果:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "68","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "68","gender" : "男"}
4.5 删除文档
4.5.1 删除语法
db.stus.remove({}) 删除所有的文档 等价 db.stus.drop() 清空集合
db.stus.remove({“属性1”:“值1”}) 删除一个或者多个文档
—remove()可以根据条件来删除文档,传递的条件的方式和find()一样
db.stus.deleteOne(“属性1”:“值1”) 删除一个文档
db.stus.deleteMany({“属性1”:“值1”}) 删除多个文档
4.5.2 删除所有文档
例子:删除集合stus中的所有文档
语法:
db.stus.remove({});
运行结果:
执行前:
{"_id" : ObjectId("61b4def1f25893b6624b2844"),"age" : "22"}
{"_id" : ObjectId("61b5869a37ce3c0fe93e33de"),"name" : "猪八戒","age" : 28.0,"gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e3"),"name" : "白骨精","age" : "16","gender" : "女"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e4"),"name" : "蜘蛛精","age" : "15","gender" : "女"}
执行后:
Fetched 0 record(s) in 2ms 0条记录
4.5.3 删除1个/多个文档
例子:删除集合stus中name为沙和尚的文档
语法:
db.stus.remove({"name":"沙和尚"});
运行结果:
删除前:
{"_id" : ObjectId("61b5bbbc37ce3c0fe93e33e6"),"name" : "沙和尚","age" : "55"}
{"_id" : ObjectId("61b5bbc437ce3c0fe93e33e7"),"name" : "沙和尚","age" : "68"}
删除后:
Fetched 0 record(s) in 2ms 0条记录
4.5.4 删除一个文档
例子:删除集合中name为“沙和尚”的第1个文档
语法:
db.deleteOne({"name":"沙和尚"});
运行结果:
执行前:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "68","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "68","gender" : "男"}
执行后:
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "68","gender" : "男"}
4.5.5 删除多个文档
例子:删除集合中name为"沙和尚"的所有文档
语法:
db.deleteMany({"name":"沙和尚"});
运行结果:
删除前:
{"_id" : ObjectId("61b587dd37ce3c0fe93e33df"),"name" : "沙和尚","age" : "68","gender" : "男"}
{"_id" : ObjectId("61b5884137ce3c0fe93e33e2"),"name" : "沙和尚","age" : "68","gender" : "男"}
删除后:
Fetched 0 record(s) in 2ms 0个记录
4.6 清空集合
语法:
db.stus.drop() 清空集合
例:清空hello数据库中的stus集合
语句:
db.stus.drop();
执行前:
{"_id" : ObjectId("61b5bd7a37ce3c0fe93e33e9"),"name" : "沙和尚","age" : "68"}
执行后:
Error: Line 1: Unexpected identifier 查不到集合信息
4.7 删除数据库
语法:
db.dropDatabase(); 删除数据库hello
例:删除hello数据库
语句:
db.dropDatabase();
运行结果:
执行前:
hello
执行后:
{
"ok" : 1.0
}
4.8 练习
练习:
1.进入my_test数据库
use my_test
2.向数据库的user集合中插入一个文档
db.user.insert({"username":"sunwukong"});
3.查询user集合中的文档
db.user.find();
4.向数据库的user集合中插入一个文档
db.user.insert({"username":"zhubajie"});
5.查询user集合中的文档
db.user.find();
6.统计数据库user集合中的文档数量
db.user.find().count();
7.查询数据库user集合中username为sunwukong的文档
db.user.find({"username":"sunwukong"});
8.向数据库user集合中的username为sunwukong的文档,添加一个address属性,属性值为huaguoshan
db.user.update({"username":"sunwukong"},{$set:{"address":"huaguoshan"}})
9.使用{username:“tangsheng”}替换username为zhubajie的文档
db.user.replaceOne({"username":"zhubajie"},{"username":"tangsheng"});
10.删除username为sunwukong的文档的address属性
db.user.update({"username":"sunwukong"},{$unset:{"address":"1"}});
11.向username为sunwukong的文档中,添加一个hobby:{citiess:[“beijing”,“shanghai”,“shenzhen”],movies:[“sanguo”,“hero”]}
MongoDB的文档的属性值也可以是一个文档,当一个文档的属性值是一个文档时,我们称这个文档时内嵌文档
db.user.update({"username":"sunwukong"},{$set:{"hobby":{"citiess":["beijing","shanghai","shenzhen"],"movies":["sanguo","hero"]}}});
12.向username为tangseng的文档中,添加一个hobby:{movies:[“A Chinese Odyssey”,“King of comedy”]}
db.user.update({"username":"tangsheng"},{$set:{"hobby":{"movies":["A Chinese Odyssey","King of comedy"]}}});
13.查询喜欢电影hero的文档
MongoDB支持直接通过内嵌文档的属性进行查询,如果要查询内嵌文档则可以通过.的形式来匹配
如果要通过内嵌文档来对文档进行查询,此时属性名必须使用引号
db.user.find({"hobby.movies":"hero"});
14.向tangseng中添加一个新的电影Interstellar
$push: 用于向数组中添加一个新的元素
db.user.update({"username":"tangsheng"},{$push:{"hobby.movies":"Interstellar"}});
15.删除喜欢beijing的用户
db.user.remove({"hobby.citiess":"beijing"});
16.删除user集合
db.user.remove({});
17.向numbers中插入20000条数据 15s
for(var i =0;i<=20000;i++){
db.numbers.insert({"num":i});
}
//---------------------------------------
var arr = []
for(var i =1;i<=20000;i++){
arr.push({"num":i});
}
db.numbers.insert(arr); //325ms
18.查询numbers中num为500的文档
db.numbers.find({"num":500});
$lte 小于等于 $lt 小于 $eq 等于 $gt 大于 $gte 大于等于
19.查询numbers中num大于5000的文档
db.numbers.find({"num":{$gt:5000}});
20.查询numbers中num小于30的文档
db.numbers.find({"num":{$lt:30}});
21.查询numbers中num大于40小于50的文档
db.numbers.find({"num":{$gt:40,$lt:50}});
22.查询numbers中num大于1996的文档
db.numbers.find({"num":{$gt:1996}});
skip(页面*每页显示的条数).limit(每页显示的条数) 分页
limit():设置显示数据的上限
23.查看numbers集合中的前10条数据 分页 limit
db.numbers.find().limit(10);
skip() 用于跳过指定数量的数据
skip(): 跳过指定数量的数据 步长 每页记录数 跳过前20条 查10条
limit(): 每页显示条数
24.查看numbers集合中的第11条到20条数据
db.numbers.find().skip(10).limit(10);
25.查看numbers集合中的第21条到30条数据
db.numbers.find().skip(20).limit(10);
26.将dept和emp集合导入到数据库中
db.dept.insert([{"deptno":"10","dname":"财务部","loc":"北京"},
{"deptno":"20","dname":"办公室","loc":"上海"},
{"deptno":"30","dname":"销售部","loc":"广州"},
{"deptno":"40","dname":"运营部","loc":"深圳"}
]);
db.dept.find();
db.emp.insert([{"empno":"7369","ename":"林冲","job":"职员","mgr":"7902","sal":800,"depno":"20"},
{"empno":"7499","ename":"孙二娘","job":"销售","mgr":"7698","sal":1600,"comm":"300","depno":"30"},
{"empno":"7521","ename":"唐三娘","job":"销售","mgr":"7698","sal":1250,"comm":"500","depno":"30"},
{"empno":"7566","ename":"卢俊义","job":"经理","mgr":"7839","sal":2975,"depno":"20"},
{"empno":"7654","ename":"潘金莲","job":"销售","mgr":"7698","sal":1250,"comm":"1400","depno":"30"},
{"empno":"7698","ename":"西门庆","job":"经理","mgr":"7839","sal":2850,"depno":"30"},
{"empno":"7902","ename":"吴用","job":"分析师","mgr":"7566","sal":3000,"depno":"20"},
{"empno":"7839","ename":"宋江","job":"董事长","sal":5600,"depno":"10"}
]);
db.emp.find();
27.查询工资小于2000的员工
db.emp.find({"sal":{$lt:2000}});
28.查询工资在1000-2000之间的员工
db.emp.find({"sal":{$gt:1000,$lt:2000}});
29.查询工资小于1000或者大于2500的员工
$or
db.emp.find({$or:[{"sal":{$lt:1000}},{"sal":{$gt:2500}}]});
30.查询办公室的所有员工
var deptno = db.dept.findOne({"dname":"办公室"}).deptno;
db.emp.find({"depno":deptno});
31.查询销售部的所有员工
var deptno = db.dept.findOne({"dname":"销售部"}).deptno;
db.emp.find({"depno":deptno});
32.查询所有mgr为7698的所有员工
db.emp.find({"mgr":"7698"});
33.为所有薪资低于1000的员工增加工资400
$inc
db.emp.updateMany({"sal":{$lt:1000}},{$inc:{"sal":400}});
4.9 分页limit
语法:
db.numbers.find().skip(20).limit(10); 分页
skip(页面*每页显示的条数).limit(每页显示的条数)
skip(): 用于跳过指定数量的数据
limit():设置显示数据的数量 (一页显示的数量)
25.查看numbers集合中的第21条到30条数据
语句:
db.numbers.find().skip(20).limit(10);
运行结果:
4.10 排序sort
查询文档时,默认情况是按照_id的值进行排列(升序)
sort() 可以用来指定文档的排序规则,sort()需要传递1个对象来指定排序规则,1:升序 -1:降序
例:员工数据按工资升序排序,工资相同的情况下,按部门降序排序
语句:
db.emp.find().sort({"sal":1,depno:-1});
运行结果:
limit,skip,sort可以任意的顺序调用,都是按sort----skip—limit顺序执行
4.11 投影
在查询时,可以在第二个参数的位置来设置查询结果的投影
—指定列 1:显示 -1:不显示
语句:
db.emp.find({},{"ename":1,"sal":1});
运行结果:
4.12 聚合
MongDB中聚合主要用于处理数据(比如统计平均值,求和等),并返回计算后的数据结果。
有点类似SQL语句中的count(*).
使用
[{
"title":"MongoDB Overview",
"description":"MongoDB is not 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 not sql database",
"by_user":"Neo4j",
"url":"http://www.neo4j.com",
"tags":["neo4j","database","NoSQL"],
"likes":70
}]
现在我们可以通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:
db.test.aggregate([{$group:{_id:"$by_user","sum_by_user":{$sum:1}}}]);
执行结果:
{ "_id" : "Neo4j", "sum_by_user" : 1.0}
{"_id" : "runoob.com","sum_by_user" : 2.0}
计算每个作者的平均点赞数:
db.test.aggregate([{$group:{_id:"$by_user","avg_likes":{$avg:"$likes"}}}]);
执行结果:
{"_id" : "Neo4j","avg_likes" : 70.0}
{"_id" : "runoob.com","avg_likes" : 55.0}
常见聚合表达式
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { s u m : " sum : " sum:"likes"}}}]) |
$avg | 计算平均值 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { a v g : " avg : " avg:"likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m i n : " min : " min:"likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m a x : " max : " max:"likes"}}}]) |
$push | 将值加入一个数组中,不会判断是否有重复的值 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { p u s h : " push: " push:"url"}}}]) |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { a d d T o S e t : " addToSet : " addToSet:"url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", first_url : { f i r s t : " first : " first:"url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.test.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", last_url : { l a s t : " last : " last:"url"}}}]) |
5 文档之间的关系
5.1 一对一关系
(one to one)
—夫妻(一个丈夫 对应 一个妻子)
—在MongoDB中,可以通过内嵌文档的形式体现出一对一的关系
db.wifiAndHusband.insert([
{"name":"黄蓉", "husband":{"name":"郭靖"}},
{"name":"潘金莲","husband":{"name":"武大郎"}}
]);
5.2 一对多关系
(one to many) 用得最多
—一个用户 对应 多个订单
—在多的这边文档,加上一那边文档的主键作为一个属性,相当于Oracle中的外键
//一对多 用户和订单
//用户
db.users.insert({"username":"swk"}); //61b601c637ce3c0fe93ed02f
db.users.insert({"username":"zbj"}); //61b601c937ce3c0fe93ed030
db.users.find();
//订单
db.order.insert({"list":["苹果","香蕉","大鸭梨"],"user_id":ObjectId("61b601c637ce3c0fe93ed02f")});
db.order.insert({"list":["西瓜","香蕉"],"user_id":ObjectId("61b601c637ce3c0fe93ed02f")});
db.order.insert({"list":["牛肉","漫画"],"user_id":ObjectId("61b601c937ce3c0fe93ed030")});
db.order.find();
//查找用户swk的订单
var user_id = db.users.findOne({"username":"swk"})._id;
db.order.find({"user_id":user_id});
运行结果:
{
"_id" : ObjectId("61b602ac37ce3c0fe93ed031"),
"list" : ["苹果","香蕉","大鸭梨"],
"user_id" : ObjectId("61b601c637ce3c0fe93ed02f")
}
{
"_id" : ObjectId("61b602b137ce3c0fe93ed032"),
"list" : ["西瓜","香蕉" ],
"user_id" : ObjectId("61b601c637ce3c0fe93ed02f")
}
5.3 多对多关系
(many to many)
—老师 对应 学生
—学生 对应 课程
—在任一多的这边文档,加上另一多边文档的主键作为一个属性,相当于Oracle中的外键
//多对多 老师和学生
//老师
db.teaher.insert({"name":"洪七公"}); //61b607d737ce3c0fe93ed034
db.teaher.insert({"name":"黄药师"}); //61b607d837ce3c0fe93ed035
db.teaher.insert({"name":"龟仙人"}); //61b607d837ce3c0fe93ed036
db.teaher.find();
//学生
db.stus.insert({"name":"郭靖","tech_ids":[ObjectId("61b607d737ce3c0fe93ed034"),
ObjectId("61b607d837ce3c0fe93ed035")]});
db.stus.insert({"name":"孙悟空","tech_ids":[ObjectId("61b607d737ce3c0fe93ed034"),
ObjectId("61b607d837ce3c0fe93ed035"),
ObjectId("61b607d837ce3c0fe93ed036")]});
//查找洪七公教的学生
var teach_id = db.teaher.findOne({"name":"洪七公"})._id;
db.stus.find({"tech_ids":teach_id});
运行结果:
{
"_id" : ObjectId("61b608ce37ce3c0fe93ed037"),
"name" : "郭靖",
"tech_ids" : [ObjectId("61b607d737ce3c0fe93ed034"), ObjectId("61b607d837ce3c0fe93ed035")]
}
{
"_id" : ObjectId("61b608ce37ce3c0fe93ed038"),
"name" : "孙悟空",
"tech_ids" : [ObjectId("61b607d737ce3c0fe93ed034"),ObjectId("61b607d837ce3c0fe93ed035"),
ObjectId("61b607d837ce3c0fe93ed036")]
}
6 MongoDB索引
索引就是用来加速查询的。数据库索引与书籍的索引类似:有了索引就不需要翻遍整本书,数据库则可以直接在索引中查找,使得查找速度能提高几个数量级。在索引中找到条目后,就可以直接跳转到目标文档的位置。
让这个比喻走个极端,可以说创建数据库索引就像确定如何组织书的索引一样。但你的优势是知道今后会做何种查询,以及那些内容需要快速查询。比如,所有的查询都包括“date”键,那么很可能需要建立一个关于“date”的索引。如果要查询用户名,则不必索引“user_num”键,因为根本不会对其进行查询。
6.1 索引简介
要掌握如何为查询配置最佳索引会有些难度,但却是非常值得努力去做。
有时候花费数分钟的查询,如果配合适当的索引可能会即刻完成。
MongoDB的索引几乎和传统的关系型数据库索引一模一样,所以如果已经掌握了那些技巧,则可以跳过本节的语法说明。
后面会有些索引的基本知识,但一定要记住这里涉及的只是冰山一角,绝大多数优化MySQL/Oracle/SQLite索引的技巧也同样适用于MongoDB。
原理
现在要依照某个键进行查找:
db.t_person.find({"username":"mark"});
当查询中仅使用一个键时,可以对该键建立索引,以提高查询速度。本例中,对“username”建立索引。
6.2 创建索引
6.2.1 创建单个索引
语法:
db.集合名词.ensureIndex({“name”:1}}
(a) 1:代表索引升序存储 -1:代表索引降序存储
(b)_id 默认自动创建索引
db.t_person.ensureIndex({"username":1})
执行后:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1.0
}
创建索引并制定索引名词:
db.集合名词.ensureIndex({“age”:1},{“name”:“age_index”}}
db.t_person.ensureInsex({"age":1},{"name":"age_index"});
执行结果:
[
{
"v" : 2,
"key" : {
"age" : 1.0
},
"name" : "age_index", //索引名词
"ns" : "hello.t_person"
}
]
对于同一个集合,同样的索引只需创建一次。反复创建是徒劳的。
对某个键创建的索引会加速对该键的查询。然而,对于其他查询可能没有帮助,即便是查询了包含了被索引的键。
例如:下面的查询就不会从先前建立索引中获得任何的性能提升。
db.t_person.find({"date":"date1"}).sort({"date":1,"username":1});
6.2.2 创建复合索引
语法:
db.集合名词.ensureIndex({“name”:1,“age”:1}}
db.t_person.ensureIndex({"username":1,"age":1}) //建立多个索引
只有使用索引前部的查询才能使用该索引。
6.2.3 创建唯一索引
语法:
db.集合名词.ensureIndex({“name”:1},{“unique”:true}}
db.t_person.ensureIndex({"name":1},{"unique":true})
执行后:
[
{
"v" : 2,
"unique" : true, //唯一索引
"key" : {
"name" : 1.0
},
"name" : "name_1",
"ns" : "hello.t_person"
}
]
创建了name唯一索引后,再插入相同的name值,会报错。
db.t_person.insert({"name":"person22","address":"33333"})
报错信息:
E11000 duplicate key error collection: hello.t_person index: name_1 dup key: { name: "person22" }
6.3 查看索引
查看索引是否创建成功
db.t_person.getIndexes();
执行结果:
[
{
"v" : 2, //版本号
"key" : {
"_id" : 1 //_id 默认创建索引
},
"name" : "_id_", //索引名词
"ns" : "hello.t_person" //索引所属命名空间
},
{
"v" : 2,
"key" : {
"name" : 1.0
},
"name" : "name_1",
"ns" : "hello.t_person"
}
]
6.4 重建索引
原来的数据也有索引效果
语法: db.集合名称.reIndex()
db.t_people.reIndex();
执行结果:
{
"nIndexesWas" : 2,
"nIndexes" : 2,
"indexes" : [
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "hello.t_person"
},
{
"v" : 2,
"key" : {
"name" : 1.0
},
"name" : "name_1",
"ns" : "hello.t_person"
}
],
"ok" : 1.0
}
6.5 删除索引
6.5.1 删除指定索引
语法:
db.集合名称.dropIndex({“name”:1});
db.t_people.dropIndex({"name":1});
6.5.2 删除所有索引
语法:
db.集合名称.dropIndexes();
db.t_person.dropIndexes();
创建索引的缺点就是每次插入、更新和删除时都会产生额外的开销。这是因为数据库不但需要执行这些操作,还要将这些操作在集合的索引中标记。因此,要尽可能少创建索引。每个集合默认的最大索引个数为64个,能够应付绝大多数情况了。
7 Java操作MongoDB
7.1 maven依赖
<!--mongoDB与java的连接-->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.0</version>
</dependency>
7.2 查询数据库
7.2.1 查询所有数据库
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:查询所有数据库
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//查询所有数据库
getDataBases(mongoClient);
}
//查询所有的数据库
public static void getDataBases(MongoClient mongoClient){
MongoIterable<String> mongoDBList = mongoClient.listDatabaseNames();
for(String dataBaseName:mongoDBList){
System.out.println(dataBaseName);
}
}
}
7.2.2 查询指定数据库
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:查询指定的数据库
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//查询指定数据库
getDataBase(mongoClient);
}
//查询指定的数据库
public static void getDataBase(MongoClient mongoClient){
//获取指定数据库
MongoDatabase helloDB = mongoClient.getDatabase("hello");
System.out.println(helloDB.getName());
}
}
7.3 查询集合
7.3.1 查询所有集合
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:查询所有集合
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//获取所有集合名称
getCollectionsNames(mongoClient);
}
//获取所有集合名称
public static void getCollectionsNames(MongoClient mongoClient){
//获取指定数据库
MongoDatabase helloDB = mongoClient.getDatabase("hello");
MongoIterable<String> collectionNames = helloDB.listCollectionNames();
for(String collectionName:collectionNames){
System.out.println(collectionName);
}
}
}
7.3.2 查询指定集合
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:查询指定集合
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//获取指定的集合
getCollectionName(mongoClient);
}
//获取指定的集合
public static void getCollectionName(MongoClient mongoClient){
//获取指定数据库
MongoDatabase helloDB = mongoClient.getDatabase("hello");
MongoCollection<Document> stusCollection = helloDB.getCollection("stus");
System.out.println(stusCollection);
}
}
7.4 查询文档
7.4.1 不带条件查询
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:不带条件查询
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//查询集合中的数据
query(mongoClient);
}
//查询集合中的数据
public static void query(MongoClient mongoClient){
MongoCollection<Document> stusCollection = mongoClient.getDatabase("hello").getCollection("stus");
FindIterable<Document> documents = stusCollection.find();
for(Document document:documents){
System.out.println(document);
System.out.println(document.get("_id"));
String name =(String) document.get("name");
System.out.println(name);
List<String> tech_ids = (ArrayList<String>)document.get("tech_ids");
System.out.println(tech_ids.toString());
}
}
}
7.4.2 带条件查询
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:带条件的查询
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//带条件的查询
queryByParam(mongoClient);
}
//带条件的查询
public static void queryByParam(MongoClient mongoClient){
MongoCollection<Document> stusCollection = mongoClient.getDatabase("hello").getCollection("stus");
Document queryDucument = new Document();
queryDucument.put("name","李四");
Document resultDocument = new Document();
resultDocument.put("_id",1);
resultDocument.put("name",1);
FindIterable<Document> queryDocuments = stusCollection.find(queryDucument).projection(resultDocument);
for(Document document:queryDocuments){
System.out.println(document);
}
}
}
7.5 插入文档
7.5.1 插入一个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:插入一个文档
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//插入一个文档
insertOne(mongoClient);
}
//插入一个文档
public static void insertOne(MongoClient mongoClient){
MongoCollection<Document> stusCollection2 = mongoClient.getDatabase("hello").getCollection("stus");
Document insertDocument = new Document();
insertDocument.put("name","李四");
insertDocument.put("age","宝安体育中心");
stusCollection2.insertOne(insertDocument);
}
}
7.5.2 插入多个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:插入多个文档
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
//获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//插入多个文档
insertMany(mongoClient);
}
//插入多个文档
public static void insertMany(MongoClient mongoClient){
MongoCollection<Document> stusCollection2 = mongoClient.getDatabase("hello").getCollection("stus");
List<Document> documentList = new ArrayList<Document>();
Document document1 = new Document();
document1.put("name","lilei");
document1.put("adress","前海壹号");
documentList.add(document1);
Document document2 = new Document();
document2.put("name","wanghua");
document2.put("adress","前海二号");
documentList.add(document2);
stusCollection2.insertMany(documentList);
}
}
7.6 修改文档
7.6.1 修改一个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:修改集合中的一条数据
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//修改集合中的一条数据
updateOne(mongoClient);
}
//修改集合中的一条数据
public static void updateOne(MongoClient mongoClient) {
MongoCollection<Document> stusCollection2 = mongoClient.getDatabase("hello").getCollection("stus");
Document queryDocument = new Document();
queryDocument.put("name", "李四");
Document updateDocument = new Document();
updateDocument.put("address", "市民中心");
stusCollection2.updateOne(queryDocument, new Document("$set",updateDocument));
}
}
7.6.2 修改多个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:修改集合中的多条数据
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//修改集合中的多条数据
updateMany(mongoClient);
}
//修改集合中的多条数据
public static void updateMany(MongoClient mongoClient) {
MongoCollection<Document> stusCollection2 = mongoClient.getDatabase("hello").getCollection("stus");
Document queryDocument = new Document();
queryDocument.put("name", "李四");
Document updateDocument = new Document();
updateDocument.put("address", "罗湖一号");
stusCollection2.updateMany(queryDocument, new Document("$set",updateDocument));
}
}
7.7 删除文档
7.7.1 删除一个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:删除集合中的一条数据
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//删除集合中的一条数据
deleteOne(mongoClient);
}
//删除集合中的一条数据
public static void deleteOne(MongoClient mongoClient){
MongoCollection<Document> stusCollection2= mongoClient.getDatabase("hello").getCollection("stus");
Document deleteDocument = new Document();
deleteDocument.put("name","孙悟空");
stusCollection2.deleteOne(deleteDocument);
}
}
7.7.2 删除多个文档
package com.tangguanlin.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:删除集合中的多条数据
* 作者:汤观林
* 日期:2021年12月18日 16时
*/
public class MongoDBTest {
public static void main(String[] args) {
// 获取连接
String host = "127.0.0.1";
int port = 27017;
MongoClient mongoClient = new MongoClient(host, port);
//删除集合中的多条数据
deleteMany(mongoClient);
}
//删除集合中的多条数据
public static void deleteMany(MongoClient mongoClient){
MongoCollection<Document> stusCollection2= mongoClient.getDatabase("hello").getCollection("stus");
Document deleteDocument = new Document();
deleteDocument.put("name","郭靖");
stusCollection2.deleteMany(deleteDocument);
}
}
8 SpringBoot整合MongoDB
这里主要以springboot应用为基础应用进行整合开发
spring Data: spring 数据框架 更友好的操作数据库
(封装集成了对大多数关系型数据库和非关系型数据库的操作)
Spring Data JPA:关系型数据库 Oracle MySQL
Spring Data Redis: 对Redis的操作 RedisTemplate
Spring Data Elasticsearch ElasticsearchTemplate
Spring Data AMQP:对MQ的操作 amqpTemplate
Spring Data MongoDB: 对MongoDB的操作 mongoTemplate
在SpringBoot框架中,使用Spring Data MongoDB操作MongoDB。
8.1 相关配置
8.1.1 maven依赖包
<!--springboot-mongodb jar-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
8.1.2 application.yml
mongodb配置
spring:
data:
mongodb:
uri: mongodb://127.0.0.1:27017
database: hello
8.2 查询当前数据库
代码:
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//查询当前数据库
@GetMapping("/queryDataBase")
public void queryDataBase(){
MongoDatabase db = mongoTemplate.getDb();
System.out.println(db.getName());
}
}
运行结果:
hello
8.3 创建集合
代码:
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//创建集合
@GetMapping("/createCollection")
public void createCollection(){
mongoTemplate.createCollection("test2");
}
}
运行结果:
teaher
test2
user
users
wifiAndHusband
8.4 删除集合
代码:
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//删除集合
@GetMapping("deleteCollect")
public void deleteCollect(){
mongoTemplate.dropCollection("test2");
}
}
运行结果:
teaher
user
users
wifiAndHusband
Person类:
package com.tangguanlin.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
/**
* 说明:person类
* 作者:汤观林
* 日期:2021年12月18日 22时
*/
@Document(collection = "t_person")
@data
public class Person {
@Id //主键类型只能为 string ObjectId,BigInteger
private String id;
private String name;
private int age;
private double salary;
@DBRef
private List<Order> orders = null;
}
Order类
package com.tangguanlin.model;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.util.Date;
/**
* 说明:订单类
* 作者:汤观林
* 日期:2021年12月18日 22时
*/
@Document(collection = "t_order")
@data
public class Order {
@Id
private ObjectId id;
@Field("order_num")
private String orderNum;
private Date createDate;
@Transient //该字段不会保存到mongodb
private String cc;
}
8.5 相关注解
8.5.1 @Document
。修饰范围:用在类上
。作用:用来映射这个类的一个对象为Mongo中一条文档数据
。属性:(value、collection)用来指定操作的集合名称
8.5.2 @Id
。修饰范围:用在成员变量、方法上
。作用:用来将成员变量的值映射为文档的_id的值
8.5.3 @Field
。修饰范围:用在成员变量、方法上
。作用:用来将成员变量以及值映射为文档中一个key、value对
。属性:(name、value)用来指定文档中key的名称,默认为成员变量名
8.5.4 @Transient
。修饰范围:用在成员变量、方法上
。作用:用来指定该成员变量,不参与文档的序列号 不映射文档字段
package com.tangguanlin.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.util.Date;
/**
* 说明:相关注解
* 作者:汤观林
* 日期:2021年12月25日 23时
*/
@Document("users") //这个类的一个对象,就代表集合中的一条文档
public class User {
@Id //用来将这个类id映射文档中的_id
private int id;
@Field("username")
private String name;
@Field
private Double salary;
@Field
private Date birthday;
}
8.6 插入文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* 说明:插入文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
@GetMapping("/insertOne")
public void insertOne(){
User user1 = new User(1,"汤观林",2236.1,new Date());
mongoTemplate.save(user1); //id存在时,更新数据
User user2 = new User(2,"小汤汤",2236.1,new Date());
mongoTemplate.insert(user2); //id存在时,报主键重复
//insert批量插入
List<User> users = new ArrayList<User>();
users.add(user1);
users.add(user2);
mongoTemplate.insert(users,User.class);
}
}
。插入重复数据时:
insert报DuplicateKeyException 提示主键重复
save:对已存在的数据进行更新
。批处理操作时:
insert 可以一次性插入整个数据,效率极高
save需遍历整个数据,单个单个插入或者更新,效率较低
8.7 查询文档
8.7.1 查询集合中的所有文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:查询集合中的所有文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//文档的查询
@GetMapping("/queryAll")
public void queryAll(){
//1.查询所有文档
//List<User> users = mongoTemplate.findAll(User.class);
List<User> users = mongoTemplate.findAll(User.class,"users");
for(User user:users){
System.out.println(user);
}
}
}
8.7.2 根据Id查询文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:根据Id查询文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//根据Id查询文档
@GetMapping("/queryById")
public void queryById(int id){
User user = mongoTemplate.findById(id, User.class);
System.out.println(user);
}
}
8.7.3 单条件查询文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:单条件查询文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//单条件查询
@GetMapping("/queryByName")
public void queryByName(String name){
Query query = Query.query(Criteria.where("name").is(name));
List<User> users = mongoTemplate.find(query,User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.7.4 多条件and查询
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:多条件and查询
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//多条件and查询
@GetMapping("/queryByAnd")
public void queryByAnd(String name,Double salary){
Query query = Query.query(Criteria.where("name").is(name).and("salary").is(salary));
List<User> users = mongoTemplate.find(query,User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.7.5 多条件or查询
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:多条件or查询
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//多条件or查询
@GetMapping("/queryByOr")
public void queryByOr(String name,Double salary){
Criteria criteria = new Criteria();
criteria.orOperator(
Criteria.where("name").is(name),
Criteria.where("salary").is(salary)
);
Query query = Query.query(criteria);
List<User> users = mongoTemplate.find(query,User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.7.6 排序
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:排序
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//排序
@GetMapping("/querySort")
public void querySort(){
Query query = new Query();
query.with(Sort.by(Sort.Order.desc("salary")));
List<User> users = mongoTemplate.find(query, User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.7.7 分页
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:分页
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//分页
@GetMapping("/queryPage")
public void queryPage(){
Query queryPage = new Query();
queryPage.with(Sort.by(Sort.Order.desc("salary")))
.skip(1) //第几页
.limit(10); //每页几条
List<User> users = mongoTemplate.find(queryPage, User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.7.8 总条数
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:总条数
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//总条数
@GetMapping("/queryCount")
public void queryCount(){
Query query = Query.query(Criteria.where("name").is("汤观林"));
long count = mongoTemplate.count(query, User.class);
System.out.println(count);
}
}
8.7.9 去重
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:去重
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//去重
@GetMapping("/findDistinct")
public void findDistinct(){
List<String> nameList = mongoTemplate.findDistinct(new Query(), "name", User.class, String.class);
for(String name:nameList){
System.out.println(name);
}
}
}
8.7.10 原生json查询
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:原生json查询
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//原生SQL语句查询
@GetMapping("/findByBasic")
public void findByBasic(){
//Query query = new BasicQuery("{'name':'汤观林'}");
Query query1 = new BasicQuery("{$or:[{'name':'汤观林'},{'name':'小汤汤'}]}","{'name':0}");
List<User> users = mongoTemplate.find(query1,User.class);
for(User user:users){
System.out.println(users);
}
}
}
8.8 修改文档
8.8.1 修改一个文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:修改一个文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//更新1条数据
@GetMapping("/updateOne")
public void updateOne(){
Query query = Query.query(Criteria.where("name").is("汤观林"));
Update update = new Update();
update.set("salary",4001.2);
mongoTemplate.updateFirst(query,update,User.class);
}
}
8.8.2 修改多个文档
package com.tangguanlin.controller;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:修改多个文档
* 作者:汤观林
* 日期:2021年12月25日 18时
*/
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//更新多条数据
@GetMapping("/updateMulti")
public void updateMulti(){
Query query = Query.query(Criteria.where("name").is("汤观林"));
Update update = new Update();
update.set("salary",4001.2);
mongoTemplate.updateMulti(query,update,User.class);
}
}
8.9 删除文档
8.9.1 删除一个文档
package com.tangguanlin.controller;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.Order;
import com.tangguanlin.model.Person;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicUpdate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:删除一个文档
* 作者:汤观林
* 日期:2021年12月18日 21时
*/
@RestController
public class MongoDBClient {
@Autowired
private MongoTemplate mongoTemplate;
//删除指定文档
@GetMapping("/removeOne")
public void removeOne(){
Query query = Query.query(Criteria.where("name").is("汤观林"));
mongoTemplate.remove(query,User.class);
}
}
8.9.2 删除多个文档
package com.tangguanlin.controller;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoDatabase;
import com.tangguanlin.model.Order;
import com.tangguanlin.model.Person;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicUpdate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 说明:删除多个文档
* 作者:汤观林
* 日期:2021年12月18日 21时
*/
@RestController
public class MongoDBClient {
@Autowired
private MongoTemplate mongoTemplate;
//删除所有文档
@GetMapping("/removeAll")
public void removeAll(){
mongoTemplate.remove(new Query(),User.class);
}
}
9 MongoDB主从集群
9.1 主从集群介绍
MongoDB副本集是有自动故障恢复功能的主从集群,有一个主节点和一个或多个从节点组成。
副本集没有固定的主节点,当主节点发生故障时,整个集群会选举一个主节点为系统提供服务以保证系统的高可用。
自动故障转移机制:当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为10秒),
合格的辅助节点将调用选举将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。
9.2 搭建副本集
等买了阿里云服务器后,统一搭建。
10 MongoDB分片集群
10.1 分片集群介绍
副本集:自动故障转移 主从复制 集群
解决问题:1.数据冗余备份 2.架构高可用
不能解决的问题: 1.单节点压力问题(硬件限制 并发访问压力)
分片集群:解决了上面的所有问题
==分片(sharding)==是指将数据拆分,将其分散存在不同机器的过程,有时也用分区来表示这个概念。
将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。
分片目的是通过分片能够增加更多的机器来应对不断的证件负载和数据,还不影响应用运行。
MongoDB支持自动分片,可以摆脱手动分片的管理困扰。集群自动切分数据做负债均衡。MongoDB分片的基本思想就是
将集合拆分成多个块。这些块分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,
甚至不需要会知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,
应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。
架构图:
。Shard: 用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组成一个一个副本集承担,防止主机单点故障
。Config Server: mongod实例,存储了整个ClusterMetadata 元数据
。Query Routers: 前端路由,客户端由此接入,且让这个集群看上去像单一数据库,前端应用可以透明使用。
。Shard Key: 片键,设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key),
片键的选取很重要,片键的选取决定了数据散列是否均匀。
_id:hash 用 _id作为片键,hash:作为负载均衡算法
10.2 搭建分片集群
等买了阿里云服务器后,