mongodb如何存储图片 mongodb存储文件如何存储_数据库

GridFS的概要

能在MongoDB中保存的Document尺寸一般有最大16Mbyte的限制。这对于保存一般的文本文件是非常足够的尺寸,但要保存一些巨大的文本文件以及视频等Binary data时,就会出现超出16Mbyte的情况。想在MongoDB中保存16Mbyte以上的文件时,通过使用GridFS这种接口,可以将数据进行多个分割来进行保存。这次,我将解说处理MongoDB中处理大尺寸文件的功能——GridFS。

GridFS的概要图

图:左青:大文件 左蓝:girdFS interface(mongofile或者是driver) 黄:1.将文件分割到chunk中,写入文件。 2.文件的元数据(文件名、尺寸等等)的写入

上图例:文件 collection

右Mongod以下:chunk用collection、Binary data、Binary data、Binary data、元数据用collection、元数据。

被分割的数据我们称之为chunk,作为Binary data保存在Document中。

用数据库来管理文件的优点

话说回来,用数据库管理文件有怎样的好处呢。

在大部分系统之中,图片/音频/视频等大尺寸Binary data使用OS的文件系统进行保存。使用文件系统的话,就能用用习惯的接口访问文件。但是根据情况不同,文件被保存在数据库中,管理起来就会更有效率。以下我试着整理了用数据库来管理文件的优点。

元数据管理简便

不仅是文件,也能通过数据库对文件相关的元数据进行同时管理。比如,文件的尺寸与制成者,制成时间等。视频文件的话也可以管理播放次数。在数据库中与文件相关的元数据也非常简便,有扩张性。另外,包含元数据的备份也很容易。

不受文件系统的上限限制

在OS中,对文件数以及目录数有上限。比如,ext3的情况下,目录内的子目录以及文件数的上限是32000。

试着简单操作下gridFS吧

在MongoDB中使用GridFS不需要特别的设定以及使用方法。基于Replica set/ sharding也可以使用。那么让我们来试着使用GridFS在MongoDB中保存文件吧。

这次我们使用在MongoDB标准版准备的Command-line tool——mongofiles。命令的选项我们将在下章进行详细说明。

首先作成用1MB.file这个文件名保存的文件。在下面的例子中作成文件尺寸1MB。

$ dd if=/dev/zero of=1MB.file bs=1M count=1

使用mongofiles,在girdtest这个数据库中保存刚刚制成的1MB的file。

$ mongofiles -v -d gridtest put 1MB.file
Wed Feb 20 15:23:27 creating new connection to:127.0.0.1:27017
Wed Feb 20 15:23:27 BackgroundJob starting: ConnectBG
Wed Feb 20 15:23:27 connected connection!
connected to: 127.0.0.1
added file: { _id: ObjectId('51246bdfa3264162c8e99716'),
filename: "1MB.file", chunkSize: 262144,
uploadDate: new Date(1361341409698),
md5: "b6d81b360a5672d80c27430f39153e2c",
length: 1048576 }
done!
运行结果如上所示的话就代表保存成功了。
关于collection结构
让我们从mongo shell开始确认GridFS的collection吧。连接mongoDB选择girdtest数据库。
$ mongo> use gridtest
确认collection。
> show collectionsfs.chunksfs.filessystem.indexes

Index之外,也有fs.chunks以及fs.files这样的collection。各自的功能分别如下所示。

fs.chunks

GridFS中,将文件作为chunk在一定尺寸中分割,保存在fs.chunks collection中。分割文件的默认尺寸是256KB。

fs.files

在fs.files collection中保存着文件名、上传时间,MD5 hash信息、文件尺寸等元数据。可以追加任意元数据。

关于被保存的元数据在官方document中有详细信息。

在下一章中,我将说明GridFS的两种操作方法:mongofiles以及ruby driver。

使用mongofiles的GridFS的操作

Mongofile是MongoDB标准版中准备的命令行工具。在安装了MongoDB的目录的bin之中。使用这个mongofiles,来试着操作GridFS吧。

各命令共通的命令行工具

V选项输出了详细内容

用d选项指定数据库名

追加文件

要追加文件就应该使用put。在此,我们在gridtest数据库中追加1MB.file这个文件。

$ mongofiles -v -d gridtest put 1MB.file

即使用同样文件名追加的,只要不被覆盖,就能作为别的object来追加。覆盖的情况时,请指定-r 选项。

$ mongofiles -v -d gridtest -r put 1MB.file

取得文件

文件的取得请使用get

$ mongofiles -v -d gridtest get 1MB.file

有同样文件名的情况,可以取得之后追加的项目。

文件的list表示

要将文件表示成表,请使用list。可以显示文件名以及文件尺寸。有同样文件名的情况下,被表示成复数。在下例中,1MB.file这个名字的文件记录了2个。

$ mongofiles -v -d gridtest list
Wed Feb 20 16:08:01 creating new connection to:127.0.0.1:27017
Wed Feb 20 16:08:01 BackgroundJob starting: ConnectBG
Wed Feb 20 16:08:01 connected connection!connected to: 127.0.0.1
1MB.file 1048576
1MB.file 1048576
image01.png 524288
image02.png 262144

删除文件

文件的删除使用delete。。

[注意]

同样文件名的数据会被全部删除,请大家注意。

$ mongofiles -v -d gridtest delete 1MB.file

文件搜索

文件的搜索使用search。指定的文字列包含文件名的情况下,会被显示。

$ mongofiles -v -d gridtest search 1MB

使用ruby的GridFS的操作

通过使用 ruby用MongoDB官方driver,可以从Ruby操作GridFS。Driver可以从gem开始安装。

$ gem install mongo

虽然不是必要的,同样地在gem中安装bson_ext的话,可以实现BSON处理的高速化。

$ gem install bson_ext

首先进行准备。要从Ruby中处理GridFS的话,需要在fs.chunks中制成index。通过在mongofiles中登陆文件,可以自动制成index。

$ dd if=/dev/zero of=1MB.file bs=1M count=1$ mongofiles -d gridtest put 1MB.file

以下是对于gridtest数据库进行取得与保存,最后删除的脚本。追加文件时,可以登陆任意元文件。

require 'mongo'
db_name = "gridtest"
@con = Mongo::Connection.new
@db = @con[db_name]
@grid = Mongo::Grid.new(@db)
@collection = @db["fs.files"]
file_id = @grid.put(File.binread("1MB.file"),
:filename => "1MB.file",
:tags => ["mongo","database","book"],
:memo => "sample file",
:owner => "mongonouchi")
puts "get file_id=#{file_id}"
puts "filename = #{@grid.get(file_id).filename}"
puts ""
@collection.find({:_id => BSON::ObjectId(file_id.to_s)}).each{ |doc|
puts doc.inspect
}
puts ""
puts "delete file_id=#{file_id}"
@grid.delete(file_id)

上述作为grid_sample.rb保存,以下是输出例。为了大家方便看,我分行写的。被输出的file_id根据环境发生改变。

$ ruby grid_sample.rb
get file_id=512ac8a2af1fe66a0e000001
filename = 1MB.file
{"_id"=>BSON::ObjectId('512ac8a2af1fe66a0e000001'),
"filename"=>"1MB.file",
"contentType"=>"binary/octet-stream",
"length"=>1048576,
"chunkSize"=>262144,
"uploadDate"=>2013-02-25 02:12:50 UTC,
"md5"=>"b6d81b360a5672d80c27430f39153e2c",
"tags"=>["mongo", "database", "book"],
"memo"=>"sample file",
"owner"=>"mongonouchi"
}
delete file_id=512ac8a2af1fe66a0e000001

其他工具

Mongofiles,在官方driver中也开发了其他能操作GridFS的工具。在此我们省略详细接受,有从Nginx开始直接GridFS操作的nginx-gridfs。

下次的主题

这次介绍了在MongoDB中处理大尺寸文件的GridFS。通过使用GridFS,图片以及动画等大文件也可以通过MongoDB来进行管理。

下次我想介绍就快发售的MongoDBv2.4的新功能。在MongoDB中追加了全文搜索,GeoJSON对应,hash document等先进功能。请大家多多期待。