传统常规做法
传统存储非结构的对象文件,通常利用服务器文件系统存储,或者使用对象存储服务器,然后在关系型数据库中保存文件路径。因此插入和查询时要经历两个步骤,效率低。
基本介绍
- 使用两个collection来存储文件内容:1.chunks,用于存储文件内容的二进制数据;2.files,用来存储文件的元数据(两个集合名称默认为:fs.files / fs.chunks)。此机制可以直接利用Mongodb已经建立的复制集或者分片。
- 存入的文件以chunksize大小(255Kb)分成一个个的文档存入进fs.chunks,存入时可以手动指定chunksize的大小。
- 小于16Mb的文件就不要用GridFS了,可以直接以单条二进制文档形式存储。
- 使用mongofiles工具或者各类程序的API进行客户端操作,将文件插入时拆分或者提取时合并。
- mongodb会自动在fs.file 和 fs.chunks两个集合上创建相关索引。
使用场景
- 文件数量过大:文件系统存储带有数量限制,当存储的内容数量过于庞大时会超出数量限制,此时利用GridFS,数量几乎是无限的。
- 只需要获取文件的部分内容,不需要全量查看文件时。
操作
上传文件
mongofiles --port 27017 --db zy --prefix my --replace --local /tmp/test.jpg put test.jpg
--db:上传到哪个数据库,没有则会自动创建。
--prefix:自己指定前缀,不指定则为fs。
--replace:文件名相同时,是否替换已经上传的文件。
test.jpg:上传系统后的文件名,为filename字段的值。
说明:默认情况下,my.file和my.chunks没有被分片。
下载文件
mongofiles --port 27017 --db zy --prefix my --local /tmp/test_new.jpg get test.jpg
--local:如果多次下载同一个文件,不改名的话则会把之前下载的覆盖。
删除文件
mongofiles --port 27017 --db zy --prefix my delete test.jpg
说明:如果有多个同名文件会一并删除。
查询文件
mongofiles --port 27017 --db zy --prefix my list "te"
mongofiles --port 27017 --db zy --prefix my search "te"
说明:第一种方法查询以te开头的文件,第二种方法查询包含te的文件。这里只是查询文件是否存在,不实际下载。
my.chunks与my.files
> db.my.files.find().pretty()
{
"_id" : ObjectId("6315662e6687fe676e829e76"),
"length" : NumberLong(251749),
"chunkSize" : 261120,
"uploadDate" : ISODate("2022-09-05T02:59:58.828Z"),
"filename" : "test_new.jpg",
"metadata" : {
}
}
> db.my.chunks.find().pretty()
{
"_id" : ObjectId("6315662e6687fe676e829e77"),
"files_id" : ObjectId("6315662e6687fe676e829e76"),
"n" : 0,
"data" : BinData(0,"/9j/4AAQSkZJRgABAQEX......)
}
获取过程:
1.通过文件名参数,匹配到my.files.filename字段,获取my.files._id。
2.根据my.files._id关联到my.chunks.files_id,获取my.chunks.data。