GridFS
该驱动程序提供了一个干净简单的接口来处理数据库中数据块文件的存储,也称为“GridFS”模式。该 API 允许您使用 Grid::文件 对象或读取和写入流。
创建 GridFS 对象 ("Grid::FSBucket")
您可以通过在数据库上调用 fs
(使用可选参数)来创建 GridFS 对象。 fs
会返回一个Grid::FSBucket
对象。
Grid::FSBucket
支持的选项包括:
选项 | 说明 |
---|---|
:bucket_name | GridFS 存储桶的名称。 默认值为 fs 。 |
:fs_name | GridFS 存储桶的名称。 优先于 bucket_name 。 默认值为fs 。 |
:chunk_size | 指定数据库中每个文件数据块的大小。 |
:write_concern | |
:write | 已弃用。 与 :write_concern 相同。 |
:read | 下载文件时使用的读取偏好(read preference)。 |
例如,您可以创建具有特定读取偏好(read preference)的 GridFS 存储桶对象:
fs_bucket = database.fs( read: { mode: :secondary } )
使用写入流
要使用写入流将文件上传到 GridFS,您可以打开一个流并直接向其写入,或者将IO
对象的全部内容一次性写入 GridFS。
要打开上传流并写入,请执行以下操作:
File.open('/path/to/my-file.txt', 'r') do |file| fs_bucket.open_upload_stream('my-file.txt') do |stream| stream.write(file) end end
要在一次调用中上传 IO 对象的全部内容:
File.open('/path/to/my-file.txt', 'r') do |file| fs_bucket.upload_from_stream('my-file.txt', file) end
写入流支持以下选项:
选项 | 说明 |
---|---|
:chunk_size | 指定数据库中每个文件数据块的大小。 |
:write_concern | 上传文件时使用的写关注(write concern)。有关如何使用写关注(write concern),请参阅CRUD下的写关注(write concern)部分。 |
:write | 已弃用。 与 :write_concern 相同。 |
这些选项可以作为写入流方法的最后一个参数提供:
fs_bucket.open_upload_stream('my-file.txt', write_concern: {w: 2}) do |stream| stream.write_concern # => #<Mongo::WriteConcern::Acknowledged:0x46980201422160 options={:w=>2}> # ... end fs_bucket.upload_from_stream('my-file.txt', file, write_concern: {w: 2})
使用读取流
要使用读取流从 GridFS 下载文件,您可以打开读取流并直接从中读取,也可以一次下载整个文件。
要打开下载流并从中读取数据,请执行以下操作:
File.open('/path/to/my-output-file.txt', 'w') do |file| fs_bucket.open_download_stream(file_id) do |stream| file.write(stream.read) end end
要一次性下载所有文件并将其写入 IO 对象:
File.open('/path/to/my-output-file.txt', 'w') do |file| fs_bucket.download_from_stream(file_id, file) end
您还可以下载由名称和(可选)修订号指定的文件。 修订号用于区分同名的文件,按上传日期排序。 传递给open_download_stream_by_name
的修订版本号可以是正数,也可以是负数。
File.open('/path/to/my-output-file.txt', 'w') do |file| fs_bucket.open_download_stream_by_name('my-file.txt', revision: -2) do |stream| file.write(stream.read) end end
要下载由名称和(可选)修订号指定的文件的全部内容:
File.open('/path/to/my-output-file.txt', 'w') do |file| fs_bucket.download_to_stream_by_name('my-file.txt', file, revision: -2) end
读取流支持以下选项:
选项 | 说明 |
---|---|
:read | 下载文件时使用的读取偏好(read preference)。 |
上面列出的部分(但不是全部)读取方法会将这些选项传递给底层读取流。 请查阅每种方法的 API 文档,以确定它是否支持特定选项。
查找文件元数据
您可以检索包含 GridFS 文件collection中文件元数据的文档。
fs_bucket.find(filename: 'my-file.txt')
删除文件
您可以通过 id 删除文件。
fs_bucket.delete(file_id)
使用 Grid::文件 对象
此对象可用于包装要使用 GridFS 插入数据库的文件以及检索的对象。
要使用原始数据创建文件:
file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt')
要从 Ruby File
对象创建文件:
file = File.open('/path/to/my-file.txt') grid_file = Mongo::Grid::File.new(file.read, :filename => File.basename(file.path))
要更改文件选项(例如数据块大小),请将选项传递给构造函数:
file = File.open('/path/to/my-file.txt') grid_file = Mongo::Grid::File.new( file.read, :filename => File.basename(file.path), :chunk_size => 1024 )
以下是文件支持的可用选项的完整列表。
选项 | 说明 |
---|---|
:chunk_size | 设置数据库中每个文件数据块的大小。 |
:content_type | 设置文件的内容类型。 |
:filename (必需) | 文件名。 |
:upload_date | 文件上传(存储)的日期。 |
插入文件
可以一次将一个文件插入数据库。 默认情况下,文件数据块插入到fs.chunks
collection中,文件元数据插入到fs.files
collection中。
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music') file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt') client.database.fs.insert_one(file)
要插入到名称前缀不是fs
的collection中,请使用:fs_name
选项访问文件系统。
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music') file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt') client.database.fs(:fs_name => 'grid').insert_one(file)
当驱动程序将第一个文件插入存储桶时,它将尝试在files
和chunks
collection上创建所需的索引。所需的索引如下:
# files collection { :filename => 1, :uploadDate => 1 } # chunks collection { :files_id => 1, :n => 1 }, { :unique => true }
注意
如果无法创建索引(例如由于当前用户没有创建索引的权限),则文件插入操作将中止。 如果应用程序没有创建索引的权限,数据库管理员必须提前创建所需的索引。
如果存储桶中已有文件,则驱动程序不会尝试创建索引,即使这些文件缺失且当前用户有权创建这些文件。 在这种情况下,数据库管理员应尽快创建所需的索引,以确保数据的完整性。
还可以对文件进行流式传输,作为直接插入的替代方法。
client.database.fs.open_upload_stream(filename) do |stream| stream.write(file) end
查找文件
要从数据库检索文件,请使用适当的筛选器调用find_one
。
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music') client.database.fs.find_one(:filename => 'new-file.txt') # Returns a Mongo::Grid::File
还可以流式传输文件,作为直接查找的替代方法。
client.database.fs.open_download_stream(file_id) do |stream| io.write(stream.read) end fs.download_to_stream(file_id, io)
删除文件
要删除文件,请将文件对象传递给delete_one
。
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music') fs = client.database.fs file = fs.find_one(:filename => 'new-file.txt') fs.delete_one(file)