关于mongodb:技术干货-如何在MongoDB中轻松使用GridFS

92次阅读

共计 3563 个字符,预计需要花费 9 分钟才能阅读完成。

GridFS 是用于存储和检索超过 16 MB 大小限度的 BSON 文档文件的标准。

留神

GridFS 不反对多文档事务

相较于将一个文件存储在单条文档中,GridFS 将文件分为多个局部或块[1],并将每个块存储为独自的文档。默认状况下,GridFS 应用的块默认大小为 255kB;也就是说,除最初一个块,GridFS 会将文件划分为 255 kB 的块。最初一个块只有必要的大小。同样,最初的那个块也不会大于默认的块大小,仅应用所需的空间以及一些其余元数据。

GridFS 应用两个汇合来存储文件。一个汇合存储文件块,另一个汇合存储文件元数据。GridFS 汇合一节具体介绍了每个汇合。

当你从 GridFS 查问文件时,驱动程序将依据须要从新组装该文件所有的块。你能够对 GridFS 存储的文件进行范畴查问。你还能够从文件的任意局部拜访其信息,例如“跳到”视频或音频文件的两头。

GridFS 不仅可用于存储超过 16 MB 的文件,而且还可用于存储您要拜访的任何文件而不用将整个文件加载到内存中。另请参阅何时应用 GridFS。

什么时候应用 GridFS

在 MongoDB 中,应用 GridFS 存储大于 16 MB 的文件。

在某些状况下,在 MongoDB 数据库中存储大型文件可能比在零碎级文件系统上存储效率更高。

如果文件系统限度了目录中文件的数量,则能够应用 GridFS 来存储所需数量的文件。

当你要拜访大文件局部的信息而不用将整个文件加载到内存中时,能够应用 GridFS 来调用文件的某些局部,而无需将整个文件读入内存。

当你心愿放弃文件和元数据在多个零碎和设施之间主动同步和部署时,能够应用 GridFS。应用地理分布的复制集时,MongoDB 能够主动将文件及其元数据散发到多个 mongod 实例和设施。

如果您须要对整个文件的内容进行原子更新,请不要应用 GridFS。或者,您能够存储每个文件的多个版本,并在元数据中指定文件的以后版本。上传文件的新版本后,您能够原子更新元数据中批示为“最新”状态的字段,而后在须要时删除以前的版本。

此外,如果文件均小于 16 MB BSON 文档大小限度,请思考将每个文件存储在单个文档中,而不是应用 GridFS。您能够应用 BinData 数据类型存储二进制数据。无关应用 BinData 的详细信息,请参见驱动程序文档。

应用 GridFS

要应用 GridFS 存储和检索文件,请应用以下任一办法:

MongoDB 驱动程序。请参阅驱动程序文档,以获取无关将 GridFS 与驱动程序一起应用的信息。

mongofiles 命令行工具。无关文档,请参见 mongofiles 参考。

GridFS Collections

GridFS 将文件存储在两个汇合中:

块存储二进制块。无关详细信息,请参见 chunks 汇合。

文件存储文件的元数据。无关详细信息,请参见文件汇合。

GridFS 通过应用存储桶名称为每个汇合增加前缀,将汇合搁置在一个公共存储桶中。默认状况下,GridFS 应用两个汇合以及一个名为 fs 的存储桶:

fs.files

fs.chunks

您能够抉择其余存储桶名称,也能够在一个数据库中创立多个存储桶。残缺汇合名称(包含存储桶名称)受命名空间长度限度。

块汇合

块 [1] 汇合中的每个文档都代表了 GridFS 中示意的文件的不同的块。此汇合中的文档具备以下格局:

{
  "_id" : <ObjectId>,
  "files_id" : <ObjectId>,
  "n" : <num>,
  "data" : <binary>
}

chunks 汇合中的文档蕴含以下字段:

chunks._id

块的惟一 ObjectId。

chunks.files_id

在 files 汇合中指定的“父”文档的_id。

chunks.n

块的序列号。GridFS 从 0 开始对所有块进行编号。

chunks.data

块 BSON 二进制类型的荷载。

文件汇合

文件汇合中的每个文档代表 GridFS 中的一个文件。

{
  "_id" : <ObjectId>,
  "length" : <num>,
  "chunkSize" : <num>,
  "uploadDate" : <timestamp>,
  "md5" : <hash>,
  "filename" : <string>,
  "contentType" : <string>,
  "aliases" : <string array>,
  "metadata" : <any>,
}

files 汇合中的文档蕴含以下一些或全副字段:

files._id

该文档的惟一标识符。_id 是您为原始文档抉择的数据类型。MongoDB 文档的默认类型是 BSON ObjectId。

files.length

文档的大小(以字节为单位)。

files.chunkSize

每个块的大小(以字节为单位)。GridFS 将文档分为大小为 chunkSize 的块,最初一个除外,后者仅依据须要而变大。默认大小为 255 KB。

files.uploadDate

GridFS 首次存储这个文档的日期。此值为有日期类型。

files.md5

过期

FIPS 140- 2 禁止应用 MD5 算法。MongoDB 驱动程序已弃用 MD5 反对,并将在将来版本中删除 MD5 的生成。须要文件摘要的应用程序应在 GridFS 内部实现它,并将其存储在 files.metadata 中。

filemd5 命令返回的残缺文件的 MD5 哈希。此值为字符串类型。

files.filename

可选的。GridFS 文件的可读名称。

files.contentType

过期

可选的。GridFS 文件的无效 MIME 类型。仅应用程序用。

应用 files.metadata 来存储与 GridFS 文件的 MIME 类型无关的信息。

files.aliases

过期

可选的。别名字符串数组。仅用于应用程序

应用 files.metadata 来存储与 GridFS 文件的 MIME 类型无关的信息。

files.metadata

可选的。元数据字段能够是任何数据类型,并且能够保留您要存储的任何其余信息。如果心愿将其余任意字段增加到文件汇合中的文档,请将其增加到元数据字段中的对象。

GridFS 索引

GridFS 应用每个块和文件汇合上的索引来提高效率。为了不便起见,合乎 GridFS 标准的驱动程序会主动创立这些索引。您还能够依据须要创立任何其余索引,以满足您的应用程序需要。

chunks 索引

GridFS 应用 files_id 和 n 字段在 chunks 汇合上应用惟一的复合索引。能够无效地检索块,如以下示例所示:

db.fs.chunks.find({ files_id: myFileID} ).sort({ n: 1} )

合乎 GridFS 标准的驱动程序将在读取和写入操作之前主动确保此索引存在。无关 GridFS 应用程序的特定行为,请参阅相干的驱动程序文档。

如果该索引不存在,则能够执行以下操作以应用 mongo shell 创立它:

db.fs.chunks.createIndex({ files_id: 1, n: 1}, {unique: true} );

files 索引
GridFS 在 files 汇合上的 filename 和 uploadDate 字段上应用索引。该索引容许高效地检索文件,如本示例所示:

db.fs.files.find({ filename: myFileName} ).sort({ uploadDate: 1} )

合乎 GridFS 标准的驱动程序将在读取和写入操作之前主动确保此索引存在。无关 GridFS 应用程序的特定行为,请参阅相干的驱动程序文档。

如果该索引不存在,则能够执行以下操作以应用 mongo shell 创立它:

db.fs.files.createIndex({ filename: 1, uploadDate: 1} );

[1] (1, 2) 在 GridFS 上下文中应用术语块与在分片上下文中应用术语块无关。

分片 GridFS

GridFS 思考两个汇合 -files 和 chunks。

chunks 汇合

要分片 chunks 汇合,请应用{files_id : 1, n : 1} 或{files_id : 1} 作为分片键索引。files_id 是一个 ObjectId,并且枯燥更改。

对于不运行 filemd5 来验证胜利上传的 MongoDB 驱动程序(例如,反对 MongoDB 4.0 或更高版本的 MongoDB 驱动程序),能够将哈希分片用于 chunks 汇合。

如果 MongoDB 驱动程序运行 filemd5,则不能应用 Hashed Sharding。无关详细信息,请参阅 SERVER-9888。

files 汇合
files 汇合很小,仅蕴含元数据。GridFS 所需的所有密钥都不适宜在分片环境中进行平均分配。保留未分片的 files 容许所有文件元数据文档保留在主分片上。

如果必须分片 files 汇合,请应用_id 字段,可能与应用程序字段联合应用。

原文链接:

https://github.com/mongodb-ch…

对于作者:张琦

Java 开发工程师,陕西西安。

正文完
 0