GridFS
驱动程序提供了一个干净、简单的接口来处理数据库中分块文件的存储,也称为“GridFS”模式。该API允许您使用Grid::File对象或读写流进行操作。
创建GridFS对象("Grid::FSBucket")
您可以通过调用fs
在数据库上创建一个GridFS对象,可选参数。 fs
返回一个 Grid::FSBucket
对象。
Grid::FSBucket
支持以下选项
选项 | 描述 |
---|---|
:bucket_name | GridFS Bucket的名称。默认为 fs 。 |
:fs_name | GridFS Bucket的名称。优先于 bucket_name 。默认为fs 。 |
:chunk_size | 指定数据库中每个文件块的大小。 |
:write_concern | 上传文件时使用的写关注。请参阅CRUD操作下的写关注部分了解如何处理写关注。 |
:write | 已弃用。与 :write_concern 相同。 |
:read | 下载文件时使用的读取偏好。 |
例如,您可以使用特定的读取偏好创建一个GridFS bucket对象
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 | 已弃用。与 :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 | 下载文件时使用的读取偏好。 |
上述某些读取方法将传递这些选项到底层的读取流。请查阅每个方法的API文档,以确定它是否支持特定选项。
查找文件元数据
您可以从GridFS文件集合中检索包含文件元数据的文档。
fs_bucket.find(filename: 'my-file.txt')
删除文件
您可以通过ID删除文件。
fs_bucket.delete(file_id)
与Grid::File对象协同工作
此对象可以用来包装要插入数据库的文件以及检索到的对象。
创建包含原始数据的文件
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
集合中,文件元数据将插入到fs.files
集合中。
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
之外名称前缀的集合中,请使用 :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
集合上创建所需的索引。所需的索引如下
# 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)