mongo对document有限制16M大小,如果插入超过此限制的数据则会报错。为了解决此问题,我们可以使用mongo的另一个特性GridFS来存储超大文件(文本文件,视频,音频等)
GridFS的使用机制就是将大文件拆分成小数据块chunk块,有序存放到mongo数据集合当中,以文档document的形式存在,这样的数据块我们称之为chunk;
chunk块的单位大小为255K,文件的最后一个chunk块除外,因为最后一个不一定正好是255Kb;
在MongoDB里,使用GridFS去存储超过16M的文件;
如下情况下将大文件存放在mongo中比在OS层面更有效:
如果系统对目录下的文件数量有限制,那么你可以考虑使用GridFS;
如果你想要访问大文件的部分信息,并且不想把整个文件都加载到内存中,则可以考虑使用GridFS;
GridFS使用两个集合来存储超大文件—- fs.files , fs.chunks:
- fs.files: 存放超大文件的元数据(medata),用来描述文件的大小,上传时间,文件名,md5校验码等等信息;
- fs.chunks: 存放超大的chunk块的二进制数据
fs.files集合结构:
{
"_id" : ObjectId("598d3f5693e6c2353332c68b"), ---文件id
"chunkSize" : 261120, ---chunk块的单位大小,一般情况下是255K
"uploadDate" : ISODate("2017-08-11T05:23:34.362Z"), ---此大文件的第一次上传时间
"length" : 0, ---文件大小
"md5" : "d41d8cd98f00b204e9800998ecf8427e", ---文件校验码
"filename" : "testfile2" ---文件名
}
注
: 此集合中其实还保留了三个可选字段,contentType, aliases, metadata, 当然应用也可以创建额外的任意字段供业务需要;
fs.chunks集合结构:
{
"_id" : ObjectId("598d3fd593e6c238c21e693d"), ---主键id
"files_id" : ObjectId("598d3fd593e6c238c21e693c"), ---文件id,对应fs.files中的id,类似于外键
"n" : 0, ---chunk序列号,一个大文件有很多的chunk,序列从0开始
"data" : BinData(0,"VGhpcyBpcyBhIHRlc3QgZmlsZSBmcm9tIEpvaG5ueQo=")
---chunk块对应的二进制数据
}
默认情况下,在第一次使用GridFS特性插入文件到mongo实例时,会自动在上述两个集合中分别创建一个索引(_id
索引除外),如下:
注:如果索引不存在,还需自行创建
rs1:PRIMARY> db.fs.files.getIndexes()
[
{
"v" : 1,
"key" : {
"filename" : 1,
"uploadDate" : 1
},
"name" : "filename_1_uploadDate_1",
"ns" : "Johnny.fs.files"
}
]
rs1:PRIMARY> db.fs.chunks.getIndexes()
[
{
"v" : 1,
"unique" : true,
"key" : {
"files_id" : 1,
"n" : 1
},
"name" : "files_id_1_n_1",
"ns" : "Johnny.fs.chunks"
}
]
两种方法:驱动调用,命令行工具mongofiles
①驱动调用:
基本mongo支持的驱动都提供调用方法,在此就不多赘述了,具体如何使用还请参阅各自驱动文档
② 命令行工具:
mongofiles
格式
mongofiles
options:
主要就是连接mongo实例的一些参数值,比如IP,端口,用户密码等等;
commands:
mongfile的一些操作处理命令,比如写文件,读文件,查看文件列表等等;
filename:
待操作的文件名称,或者GridFS中文件对象名(fs.files集合中的filename字段值);
权限:
如果mongo实例开启了auth认证服务,则在执行mongofile命令需要给予用户readWrite权限即可;
详细参数:
options其实没什么可说的,基本上就是一些连接参数;
filename也没什么讲的,就是文件对象名称,如果你要get文件,则必须使用的是fs.files集合中filename字段的值(如果有update过,则使用最近更新过的名称)
commands:
这个需要好好说说
list:
列出GridFS存储的所有文件名,以及对应的大小
search:
搜索文件名包含某些字符串的文件,并列出, search “test”
put:
将文件写入GridFS存储中 put “testfile”
get:
从GridFS中提取文件到当前路径下,如果想要更改存放目录,则可以在options中使用–local 参数指定,get “testfile”
get_id:
根据GridFS中文件对应的file_id提取文件到当前路径下,3.2以后的新功能,get_id ‘ObjectId(“598d3fd593e6c238c21e693c”)’
delete:
从GridFS中删除指定文件,delete “testfile”
delete_id:
根据file_id删除指定文件, delete_id ‘ObjectId(“598d3fd593e6c238c21e693c”)’
例子:
mongofiles --host 10.25.161.14:27027 -uAdmin -padmin123 -d Johnny --authenticationDatabase admin put testfile.pdf
参数说明:
--host, --port, -u, -p, --authenticationDatabase都与其他mongo命令参数一致的用法,不再赘述
put: 就是上述讲过的commands命令
testfile:对应你想要存储到数据库的超大文件名
上述例子就是将testfile.pdf图片存放到数据库中