MongoDB学习笔记
“nosql现在在网站开发中应用的越来越广泛,其中的MongoDB被大量使用。MongoDB 作为一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,也是我们所必须掌握的一个产品。”
首先我需要感谢一下这两位老哥:konghouy和 DeeJay_Y,我是以他们的文章为基础进行学习的。献上他们的文章链接:
https://blog.csdn.net/konghouy/article/details/90146763
https://www.jianshu.com/p/72fc4409936c
另外还有菜鸟教程的链接:https://www.runoob.com/mongodb/mongodb-tutorial.html
MongoDB官网链接:https://www.mongodb.org.cn/
正文
01
什么是NoSql
NoSQL最常见的解释是“non-relational”, “Not Only SQL”也被很多人接受。NoSQL仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的ACID特性。NoSQL有如下优点:易扩展,NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。无形之间也在架构的层面上带来了可扩展的能力。大数据量,高性能,NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。
https://baike.baidu.com/item/NoSQL/8828247?fr=aladdin
NoSql可以分成4类:
-
键值(Key-Value)存储数据库
这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value模型对于IT系统来说的优势在于简单、易部署。但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。举例如:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB。用大白话来讲就是一个map
-
列存储数据库
这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。如:Cassandra, HBase, Riak。这个我没用过,不甚了解。
-
文档型数据库
文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB, MongoDb. 国内也有文档型数据库SequoiaDB,已经开源。存储的内容是类似JSON格式的数据。
-
图形(Graph)数据库
图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。如:Neo4J, InfoGrid, Infinite Graph。
02
什么是MongoDB
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
03
MongoDB安装
具体安装过程自己百度吧。这里我给出菜鸟教程的安装教程地址:https://www.runoob.com/mongodb/mongodb-window-install.html
我自己在安装没有遇到坑,但是这里收集了别人遇到的问题。
-
install mongoDB compass
安装过程中勾选了安装install mongoDB compass,导致安装程序一直卡在那块。最后要重新安装了一次才解决了问题。mongoDB compass是个图形化界面,后期可以自己安装。MongoDB图形化界面挺多的,自己后期挑个喜欢的就好。我个人喜欢robo 3T
-
安装在其他盘时,安装过程提示错误。
MongoDB默认装在C盘,安装程序可以直接获取管理员权限。但是当我们装在其他盘时,就没这么好运了。这就需要我们使用管理员身份运行安装程序。
-
安装MongoDB服务出现问题
当程序安装完成之后,就需要安装windows服务了,MongoDB中已经为我们写好了配置文件,通过这个配置文件,即可安装windows服务。具体的命令是:mongod --config "E:\MongoDB\bin\mongod.cfg" --install本想着,安装服务然后启动服务就可以可以使用了,但是这样却出现了问题:Unrecognized option:mp 这就令人非常抓狂了,配置文件是官方提供的,它怎么能说mp是无效的属性呢?直接干掉这个mp这一行就行了。
-
MongoDB需要配置数据文件存放位置和日志存放位置,不然无法运行。
-
配置文件中不能使用Tab键进行缩进。属性名与属性值之间,必须用 :空格 进行连接,如果不添加空格,属性将无法识别
MongoDB服务相关的命令:
删除windows服务:sc delete MongoDB
启动服务 :net start MongoDB
停止服务:net stop MongoDB
更新服务配置:mongod -f E:\MongoDB\bin\mongod.cfg
04
数据库连接及权限管理
使用MongoDB中有一个很大的困惑,既然不需要密码就可以登录?那它的安全性如何保证呢?权限划分又是如何进行呢?对比MySQL在安装成功之后就会有个初始密码,MongoDB是不是不安全呢?
MongoDB默认是不需要输入用户名和密码,客户就可以登录的,获得管理员权限。不过会出现好多好多Warning。
出于安全性的考虑,我们还是要为其设置用户名和密码。
步骤1:先以不需要密码的形式登录,进入admin库。
1 use admin;
步骤二:往admin表中插入一个超级管理员用户。
db.createUser({
user:"root",
pwd:"root",
roles:[{role:"root",db:"admin"}]
})
步骤三:查看用户是否插入成功。
1 show users
步骤四:在配置文件中添加auth=true
注意,如果是使用MongoDB自动生成的配置文件,写法则与自建的配置文件不同。不能用tab,冒号后面必须有个空格。具体参数参考:
http://docs.mongodb.org/manual/reference/configuration-options/
// 增加这两行 security: authorization: enabled
步骤五:重启MongoDB。
net stop mongodb (关闭服务)
net start mongodb (开启服务)
步骤六:使用账户密码连接MongoDB,authenticationDatabase 参数为要验证的数据库。
mongo.exe --host "localhost" --port "27017" -u "root" -p "root" --authenticationDatabase "admin"
相关数据库角色:
-
数据库用户角色(Database User Roles):
read:授予User只读数据的权限。
readWrite:授予User读写数据的权限。
-
数据库管理角色(Database Administration Roles):
dbAdmin:在当前dB中执行管理操作。
dbOwner:在当前DB中执行任意操作。
userAdmin:在当前DB中管理User。
-
备份和还原角色(Backup and Restoration Roles):
backup
restore
-
跨库角色(All-Database Roles):
readAnyDatabase:只能在admin库中添加,授予在所有数据库上读取数据的权限。
readWriteAnyDatabase:只能在admin库中添加,授予在所有数据库上读写数据的权限。
userAdminAnyDatabase:只能在admin库中添加,授予在所有数据库上管理User的权限。
dbAdminAnyDatabase:只能在admin库中添加,授予管理所有数据库的权限。
-
集群管理角色(Cluster Administration Roles):
clusterAdmin:只能在admin库中添加,授予管理集群的最高权限。
clusterManager:只能在admin库中添加,授予管理和监控集群的权限。
clusterMonitor:只能在admin库中添加,授予监控集群的权限,对监控工具具有readonly的权限。
hostManager:只能在admin库中添加,管理Server。
-
超级管理员:
root : 只能在admin库中添加,超级账号,超级权限
相关角色的操作:
1、 在shell中切换用户角色:
db.auth(“user”,“pwd”);
2、修改密码:
方法1:db.changeUserPassword(“usertest”,“changepass”);
方法2:db.updateUser(“usertest”,{pwd:“changepass1”});
3、修改权限:
// updateUser它是完全替换之前的值
db.updateUser(“usertest”,{roles:[ {role:“read”,db:“testDB”} ]})
4、增加权限:
# 修改权限
db.grantRolesToUser( “usertest”, [ {role:“readWrite”, db:“testDB”}, {role:“read”, db:“testDB”} ])
5、删除权限:
db.revokeRolesFromUser(“usertest”,[{role:“read”, db:“testDB”}]);
05
MongoDB的数据类型
各类型对应的数字表示:
上面的大部分类型都是显而易见的,但是有必要详细解释一下对象 id类型。我们上面说了,对象 id类型是一个 12字节的唯一 id。每个字节 2位 16进制数(1字节8位,4位一个十六进制数),因此整个 id类型是一个 24位的字符串。其结构如下表所示:
前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时。接下来三个字节表示机器号,一般是机器名的hash值。这可以保证不同机器产生的id不会冲突。接下来两个字节表示进程id号,保证统一机器不同进程产生的id不冲突。最后三个是计数器的计数值,对于任意一秒钟,可以产生2^24个数。
06
MongoDB的一些概念
MongoDB的三个特殊库:
admin:从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。
config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
MongoDB中严格区分大小写,特别是命令。
MongoDB的连接:
MongoDB中的两种连接方式:
direct:只连接一台服务器,不管他是不是主服务器。
replicaSet:连接多台服务器。
07
MongoDB的基本使用
1、创建数据库:
// 如果数据库不存在,那么在插入第一条数据后,便会自动创建数据库
use dbName;
【注意】数据库创建,必须要插入一条数据后, show dbs 命令才会显示,数据库已经添加
2、查看数据库
// 显示权限范围内的数据库db;
// 显示当前数据库
show dbs;
3、删除数据库
// 删除当前数据库 db.dropDatabase();
4、创建集合
db.createCollection(name, options);
db.createCollection("mycol",{
capped : true,
autoIndexId : true,
size :6142800,
max : 10000
} )
参数说明:
-
name: 要创建的集合名称
-
options: 可选参数, 指定有关内存大小及索引的选项
options 可以是如下参数:
注意:
-
如果要创建固定大小的集合,必须显示创建,自动创建的集合都是不定长的集合。
-
插入文档时,会先判断size参数,空间足够才判断max,只有两者都满足,才能插入成功。
5、获取集合:
db.getCollection("集合名");
db.集合名
6、查看所有集合:
show tables;show collections; // 这个命令更适合MongoDB
7、删除集合:
db.getCollection("集合名").drop()// 这里要注意和删除数据库进行区分
db.dropDatabase();
8、插入文档:
// 参数为json,可以是数组,也可以是对象,只要满足json格式就行 db.getCollection("集合名").insert({"name":"张三","age":15});
db.getCollection("集合名").save({"name":"张三","age":15});
db.getCollection("集合名").insertOne({"name":"张三","age":15});
db.getCollection("集合名").insertMany([ {"name":"张三","age":15}, {"name":"栗子","age":25}]);
说明:
-
insertOne()只能插入一个文档,如果传入一个数组,则报错。
-
insertMany()只能插入数组,如果传入不是数组,则报错。
-
insert()如果传入数组,则插入多个文档;如果传入单个对象,则插入一个文档;如果_id不填写,自动生成objectId;如果_id已存在,则报错。
-
save()和insert()基本一样,但是当_id存在时,save()会直接更新该_id对应的整个文档
9、查询文档
// query为查询条件,projection为映射字段
db.getCollection("集合名").find(query, projection);
// 相当于SQL: select <projection> from "集合名" where <query>
说明:
-
$lt ==> less than
-
$gt => greater than
-
$lte ==> less than or equal
-
$ne ==> not equal
-
多个条件逗号隔开,默认就是and,如果是or,则需要$or:[{条件},{条件}]。$or中每个元素都必须是对象。
-
$type的值可以是类型对应的数字,也可以是类型字符串(首字母需要小写)
// 查询姓名中有个张字的15-20岁的学生,他可能是四班的,// 也有可能是李四老师教的学生 db.getCollection("student").find({
name:"^\w*张\w*$",
age:{$lt:20,$gt:15},
$or:[
{class:"四班"},
{teacher:"李四"}
]
});
projection :可选,使用投影操作符指定返回的键。省略时默认全部返回。_id是一直都返回的,如果不需要返回,必须显式指定不返回。
栗子:
// 返回item和qty字段,其他全部不返回 db.getCollection("student").find( {a:{$type:"string"}},{ item: 1, qty: 1, _id:0 } )
10、格式化查询结果
// 将文档格式化输出,在shell中有用,但是在可视化工具中用途不大 db.getCollection("student").find({}).pretty();
11、更新文档:
// 有两种方式:update和save 1:db.getCollection("student").update(
{<query>},
{<update>},
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
); 2:db.getCollection("student").save({document});
说明:
-
save()以文档中_id为条件进行查询,如果存在,则整个文档进行更新。
-
update更灵活,
为查询条件, 为更新的字段,剩下三个参数。 -
:查询条件,和find()中的查询条件写法一样。 -
: 更新的操作符,用于细化更新字段,如$set、$inc等。 -
upsert:可选。如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。相当于update + insert。
-
multi:可选。mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
-
writeConcern:可选,抛出异常的级别。(个人感觉没啥卵用)
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
update(更新的操作符)说明:
-
$inc
{ $inc : { field : value } }。意思对一个数字字段field增加value
// 表示给_id为123的文档的price字段增加5 db.col.update({_id:123},{$inc:{price:5}})
【注意】value可以为整数也可以为负数。
-
$set
{ $set : { field : value } }。赋值语句
// 相当于SQL中set语句 db.col.update(
{
title:1.0,
title:{$type:1}
},
{
$set:{title:"张",aa:"aa"},
$inc:{bb:9}
}
);
-
$unset
{ $unset : { field : 任意内容} }。就是删除field字段
db.getCollection('account').update( {title:"张"}, {$unset:{aa:1,bb:1}})
-
$push
{ $push : { field : value } }。把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去。
db.getCollection('account').update( {title:"张"}, {$push:{tags:"mysql"} })
-
$pushAll
{ $pushAll : { field : value_array } }。将数组中的每一项,追加多个值到一个数组字段内【高版本的MongoDB中没有这个命令,反正我的没有】
db.getCollection('account').update( {"userid":3}, {$pushAll:{"name":["N1","N2"]}} )
-
$addToSet
{ $addToSet : { field : value } }。增加一个值到数组内,而且只有当这个值不在数组内才增加。
db.getCollection('account').update( {title:"张"}, {$addToSet:{tags:"222"}})
-
$pop
删除最后一个值:{ $pop : { field : 1 } }
删除第一个值:{ $pop : { field : -1 } }注意:值只能是1或-1,否则报错。
db.getCollection('account').update({title:"张"},{$pop:{tags:1}})
-
$pull
$pull : { field : value } }。从数组field内删除一个等于value值。
db.getCollection('account').update( {title:"张"}, {$pull:{tags:"333"}})
-
$pullAll
{ $pullAll : { field : value_array } }。可以一次删除数组内的多个值。
db.getCollection('account').update( {title:"张"}, {$pullAll:{tags:["222","mysql"]}})
-
$ 操作符
$美元符号是在查询数组时才用的,作为定位符,匹配第一个符合查询条件的值的位置
说明:
12、删除文档
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
);
说明:
-
justOne:(可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
注意:在写参数时,以下两种方式都是可以的,第一种方法可以针对性的指定参数,但是必须写参数名。第二种方法可以省略参数名,但是必须把前面的参数值也填写完整,而且顺序不能错。
1:db.getCollection('account').remove( {title:"MongoDB 教程"}, {justOne:1}); 2:db.getCollection('account').remove({title:1},true);
13、限制文档输出数量:
db.getCollection('account').find().limit(数量);
14、输出文档时跳过前面的文档
db.getCollection('account').find().skip(数量);
提示:
limit和skip组合起来就可以实现分页了。
// 先由skip跳过前面没用的记录,再用limit限定当前页面显示的内容 db.getCollection('account').find().skip(数量).limit(数量);
15、排序
db.getCollection('account').sort({title:-1,likes:1})
说明:
-
按顺序进行排序,如例子中先按title排序,相同title的再按likes排序。
-
-1代表从大到小,desc,倒序。
-
1代表从小到大,asc,顺序。
16、索引
和普通关系型数据库一样,建立索引可以提升数据查找的速度
db.collection.createIndex(keys, options) db.col.createIndex({"title":1})
keys对象参数为1表示正序建立索引,-1表示逆序建立索引。如果添加多个属性为联合索引。
红色圈圈圈出来的是我个人认为比较常用的
其他索引操作:
- 查看集合索引
db.col.getIndexes()
- 查看集合索引大小
db.col.totalIndexSize()
- 删除集合所有索引
db.col.dropIndexes()
- 删除集合指定索引
db.col.dropIndex("索引名称")
- 设置定时删除任务(利用了expireAfterSeconds)
利用 TTL 集合对存储的数据进行失效时间设置:经过指定的时间段后或在指定的时间点过期,MongoDB 独立线程去清除数据。
// 例如在数据记录中 createDate 为日期类型之后180删除
db.col.createIndex({"createDate": 1},{expireAfterSeconds: 180})
如果expireAfterSeconds的值为0,则以索引字段的值的实际时间去进行删除。
其他注意事项:
- 索引关键字段必须是 Date 类型。
- 非立即执行:扫描 Document 过期数据并删除是独立线程执行,默认 60s 扫描一次,删除也不一定是立即删除成功。
- 单字段索引,混合索引不支持。
08
数据库备份与恢复
1、备份
2、恢复
09
数据库性能监控
【注意】在使用身份验证模式下,需要使用root权限来查看数据库性能。一般用户没有这个能力,无法打开性能监控。
输出字段解析:
10
数据库高级查询
前面介绍的内容都是数据基本的增删改查,但是NoSQL出现了一个多个集合之间数据组织的问题。NoSQL不像关系型数据库,通过关系来实现多数据直接的结合。要想实现多文档,多集合的管理数据,就要使用应用层来回查询。使用这种方式将会消耗大量的网络数据,不利于数据库操作的效率。
但是MongoDB作为最像关系型数据库的非关系型数据库,也为我们提供了多集合联合查询的功能
1、聚合通道
MongoDB中聚合的方法使用aggregate()。聚合就是可以对数据查询进行多次过滤操作,以达到复杂查询的目的。聚合查询函数接收一个数组,数组里面是若干个对象,每个对象就是一次查询的步骤。前一个查询的查询结果,作为后一个查询的筛选内容。
这种聚合通道,和Java8中的集合的stream流操作很类似。
db.getCollection("student").aggregate( [ { "$match" : { "age" : { "$gt" : 20.0 } } }, { "$lookup" : { "from" : "room", "localField" : "class", "foreignField" : "name", "as" : "num" } }, { "$unwind" : { "path" : "$num", "includeArrayIndex" : "l", "preserveNullAndEmptyArrays" : false } }, { "$project" : { "num.name" : 1.0 } }, { "$count" : "cou" } ]);
下面我只详细说明部分操作符:
一些随便的查询:
注意:如果查询中用到内嵌文档的属性,要整个字段名用引号括起来,包括根文档的。例如查询13
13
Java连接操作MongoDB
有三种连接方式,官方提供的jdbc连接(mongo-java-driver)和 spring-boot-starter-data-mongodb ,以及spring-data-jpa(我不喜欢用jpa,所以这里不介绍)
1、mongo-java-driver
步骤一:添加jar包
<dependency> <groupId>org.mongodbgroupId> <artifactId>mongo-java-driverartifactId> <version>3.12.2version> dependency>
步骤二:连接到 mongodb 服务(MongoDB连接有很多的重载方法,这里只给出几种,其他自己去看MongoClient)
// 连接到 mongodb 服务
1、MongoClient mongoClient = new MongoClient( "localhost" ); // 用指定主机的默认端口连接
2、MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 用指定主机指定端口连接
3、MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
MongoClient mongoClient = new MongoClient( "localhost" , builder ); // 填写相关连接配置
4、ListserverAddressList = new ArrayList<>(2);
serverAddressList.add(new ServerAddress("192.168.1.117", 27015));
serverAddressList.add(new ServerAddress("192.168.1.116", 27016));
MongoClient mongoClient = new MongoClient( serverAddressList ); // 连接多个MongoDB
5、MongoClient mongoClient = new MongoClient( new MongoClientURI("mongodb://root:root@localhost:27017") ); // 使用连接地址
6、MongoClient mongoClient = new MongoClient( new ServerAddress("localhost",27017) // 使用密码
,MongoCredential.createScramSha1Credential("root", "admin", "root".toCharArray())
,MongoClientOptions.builder().build());
步骤三:选择数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
注意:如果数据库不存在,插入一条数据后,会自动创建数据库
步骤四:选择集合
MongoCollectioncollection = mongoDatabase.getCollection("account");
注意:如果集合不存在,插入一条数据后,会自动创建集合
步骤五:常规操作,如新增,修改,删除,查找,统计
// 插入 Document document = new Document("id", "123") .append("name", "微三云") .append("date", new Date()); collection.insertOne(document);
public class Document implements Map
Document 对象继承自map和Bson,Bson这个接口在MongoDB的API中很常见。用到Bson的地方基本都可以丢个Document进去。
Document的创建方式也有很多:
// 删除
DeleteResult deleteOne = collection.deleteOne(Document.parse("{id:3456}")); // 删除一条
DeleteResult deleteMany = collection.deleteMany(Filters.eq("name", "张三")); // 删除多条
System.err.println(deleteMany.getDeletedCount()); // 查看删除的结果
// 更新
collection.findOneAndUpdate(Filters.eq("name", "张三"), Document.parse("{$set:{name:\"李阳\"}}")); // 这个命令是只更新一条记录
collection.updateMany(Filters.eq("id", 3456), Document.parse("{$set:{name:\"李\"}}")); // 更新多条
collection.updateOne(Filters.eq("id", 3456), Document.parse("{$set:{name:\"李\"}}")); // 更新找到的第一条,默认顺序是数据库文档顺序
// 查找
FindIterablefind = collection.find(Filters.eq("id", 3456)); MongoCursor iterator = find.iterator(); while(iterator.hasNext()) { Document next = iterator.next(); System.err.println(next); }
还有很多其他方法:
2、spring-boot-starter-data-mongodb
其实这个是spring在MongoDB-Java-driver上进行封装的,能够自动返回Java对象
使用步骤:
步骤一:搭好spring boot环境,加入spring-boot-starter-data-mongodb启动器依赖
步骤二:导入项目
步骤三:添加配置,properties配置(yml配置也行,自己整理格式)
spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=myMongodb # 默认没有账号密码 spring.data.mongodb.username=hongcheng spring.data.mongodb.password=hongcheng
步骤四:注入MongoTemplate(常规操作)或者GridFsTemplate(基于MongoDB来持久存储文件,后面引用另外一位老哥的文章介绍)
@Autowired private MongoTemplate mongoTemplate;
步骤五:写代码
MongoTemplate里面有很多方法,基本实现了增删改查的全部功能。而且也提供了直接执行json命令的方法。可以说就算你不会用这个东西,只要你会写MongoDB的基础命令,就能用了。
public Document executeCommand(final String jsonCommand) ;
public Document executeCommand(final Document command);
public Document executeCommand(Document command, @Nullable ReadPreference readPreference);
public void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch) ;
public
Assert.notNull(action, "DbCallback must not be null!");
try {
MongoDatabase db = prepareDatabase(this.doGetDatabase());
return action.doInDB(db);
} catch (RuntimeException e) {
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
}
}
public
public
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(callback, "CollectionCallback must not be null!");
try {
MongoCollection
return callback.doInCollection(collection);
} catch (RuntimeException e) {
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
}
}
这里我放另外一个大哥的文档,介绍怎么使用aggregate:https://blog.csdn.net/C18298182575/article/details/100698885
14
MapReduce操作
这里再讲下MapReduce操作,在借用另外一个大哥的文章:https://www.cnblogs.com/chenpingzhao/p/7913247.html
15
Spring Boot使用mongo的GridFS模块
再来一个老哥的文档(以下内容来自该文档,可直接前往查看):
https://www.cnblogs.com/mengrennwpu/p/8849551.html
Spring Boot使用mongo的GridFS模块
1. GridFS简介
GridFS是Mongo的一个子模块,使用GridFS可以基于MongoDB来持久存储文件。并且支持分布式应用(文件分布存储和读取)。作为MongoDB中二进制数据存储在数据库中的解决方案,通常用来处理大文件,对于MongoDB的BSON格式的数据(文档)存储有尺寸限制,最大为16M。但是在实际系统开发中,上传
的图片或者文件可能尺寸会很大,此时我们可以借用GridFS来辅助管理这些文件。
GridFS不是MongoDB自身特性,只是一种将大型文件存储在MongoDB的文件规范,所有官方支持的驱动均实现了GridFS规范。GridFS制定大文件在数据库中如何处理,通过开发语言驱动来完成、通过API接口来存储检索大文件。
2. GridFS使用场景
(1) 如果您的文件系统在一个目录中存储的文件的数量有限,你可以使用GridFS存储尽可能多的文件。
(2) 当你想访问大型文件的部分信息,却不想加载整个文件到内存时,您可以使用GridFS存储文件,并读取文件部分信息,而不需要加载整个文件到内存。
(3) 当你想让你的文件和元数据自动同步并部署在多个系统和设施,你可以使用GridFS实现分布式文件存储。
3. GridFS存储原理
GridFS使用两个集合(collection)存储文件。一个集合是chunks, 用于存储文件内容的二进制数据;一个集合是files,用于存储文件的元数据。
GridFS会将两个集合放在一个普通的buket中,并且这两个集合使用buket的名字作为前缀。MongoDB的GridFs默认使用fs命名的buket存放两个文件集合。因此存储文件的两个集合分别会命名为集合fs.files ,集合fs.chunks。
当然也可以定义不同的buket名字,甚至在一个数据库中定义多个bukets,但所有的集合的名字都不得超过mongoDB命名空间的限制。
MongoDB集合的命名包括了数据库名字与集合名字,会将数据库名与集合名通过“.”分隔(eg:
当把一个文件存储到GridFS时,如果文件大于chunksize (每个chunk块大小为256KB),会先将文件按照chunk的大小分割成多个chunk块,最终将chunk块的信息存储在fs.chunks集合的多个文档中。然后将文件信息存储在fs.files集合的唯一一份文档中。其中fs.chunks集合中多个文档中的file_id字段
对应fs.files集中文档”_id”字段。
读文件时,先根据查询条件在files集合中找到对应的文档,同时得到“_id”字段,再根据“_id”在chunks集合中查询所有“files_id”等于“_id”的文档。最后根据“n”字段顺序读取chunk的“data”字段数据,还原文件。
4. 存储过程
fs.files 集合存储文件的元数据,以类json格式文档形式存储。每在GridFS存储一个文件,则会在fs.files集合中对应生成一个文档。
fs.files集合中文档的存储内容如下:
fs.chunks 集合存储文件文件内容的二进制数据,以类json格式文档形式存储。每在GridFS存储一个文件,GridFS就会将文件内容按照chunksize大小(chunk容量为256k)分成多个文件块,然后将文件块按照类json格式存在.chunks集合中,每个文件块对应fs.chunk集合中一个文档。一个存储文件会对应一到多个chunk文档。
fs.chunks集合中文档的存储内容如下:
为了提高检索速度 MongoDB为GridFS的两个集合建立了索引。fs.files集合使用是“filename”与“uploadDate” 字段作为唯一、复合索引。fs.chunk集合使用的是“files_id”与“n”字段作为唯一、复合索引。
5. 注意事项
(1) GridFs不会自动处理md5值相同的文件,也就是说,同一个文件进行两次put命令,将会在GridFS中对应两个不同的存储,对于存储来说,这是一种浪费。对于md5相同的文件,如果想要在GridFS中只有一个存储,需要通过API进行扩展处理。
(2) MongoDB 不会释放已经占用的硬盘空间。即使删除db中的集合 MongoDB也不会释放磁盘空间。同样,如果使用GridFS存储文件,从GridFS存储中删除无用的垃圾文件,MongoDB依然不会释放磁盘空间的。这会造成磁盘一直在消耗,而无法回收利用的问题。如何释放磁盘空间?
(1) 可以通过修复数据库来回收磁盘空间,即在mongo shell中运行db.repairDatabase()命令或者db.runCommand({ repairDatabase: 1 })命令。(此命令执行比较慢)。
使用通过修复数据库方法回收磁盘时需要注意,待修复磁盘的剩余空间必须大于等于存储数据集占用空间加上2G,否则无法完成修复。因此使用GridFS大量存储文件必须提前考虑设计磁盘回收方案,以解决mongoDB磁盘回收问题。
(2) 使用dump & restore方式,即先删除mongoDB数据库中需要清除的数据,然后使用mongodump备份数据库。备份完成后,删除MongoDB的数据库,使用Mongorestore工具恢复备份数据到数据库。当使用db.repairDatabase()命令没有足够的磁盘剩余空间时,可以采用dump & restore方式回收磁盘资源。如果MongoDB是副本集模式,dump &
restore方式可以做到对外持续服务,在不影响MongoDB正常使用下回收磁盘资源。
6. 代码示例
花了这么久,总算结束了,参考了很多人的文章,有些没有直接写出来,先说声抱歉了,毕竟有些我自己都找不到文章地址了。
如果这篇文章对你有用,给我点个赞好么。
参考文章:
https://blog.csdn.net/konghouy/article/details/90146763
https://www.jianshu.com/p/72fc4409936c
https://blog.csdn.net/C18298182575/article/details/100698885
https://www.cnblogs.com/chenpingzhao/p/7913247.html
https://www.runoob.com/mongodb/mongodb-tutorial.html
https://www.mongodb.org.cn/