翻译自 : http://gihyo.jp/dev/serial/01/mongodb/0007
本文永久链接地址:https://www.askmac.cn/archives/mongodb-gridfs.html
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等先进功能。请大家多多期待。
Comment