mongodb - GridFS save/read file 예제
참조 - http://linuxism.tistory.com/1405
MongoDB GridFSTop
IntroductionTop
MongoDB 안에 Large Objects 를 저장할 수 있는 파일시스템 입니다. 간단하게 파일을 저장하여 사용할 수 있고, MongoDB가 설치되어 있으면 자매품격으로 따라오는 녀석입니다. 저장방식은 1개의 파일당 MAX 2GB 사이즈까지 저장가능하며, 256k chunk 단위로 나누어져 저장합니다. 이는 chunks collections 에 나누어진 document 으로 저장됩니다. 이와 meta, filename, content type, 다른 옵션들은 files collection 에 저장됩니다. 즉 files collection 과 chunks collections 은 1:n 관계를 가진다.
SpecTop
GridFS 는 데이타를 저장하기 위해 2개의 collection 구성됩니다.
- files : metadata 포함
- chunks : binary chunks (BSON)
GridFS는 하나의 데이타베이스 안에서 네임스페이스를 가질 수 있습니다. 아무것도 지정하지 않은면 기본은 fs 이며, fs.files, fs.chunks Collection이 기본으로 생성됩니다.
2개의 collection 구성Top
filesTop
files의 document 구조를 알아보겠습니다.
{"_id" : <unspecified>, // unique ID for this file"length" : data_number, // size of the file in bytes"chunkSize" : data_number, // size of each of the chunks. Default is 256k"uploadDate" : data_date, // date when object first stored"md5" : data_string // result of running the "filemd5" command on this file's chunks}
위 내용은 기본적으로 생성되는 필드이며, 아래와 같이 임의로 지정한 여러필드를 추가할 수 있습니다.
{"filename" : data_string, // human name for the file"contentType" : data_string, // valid mime type for the object"aliases" : data_array of data_string, // optional array of alias strings"metadata" : data_object, // anything the user wants to store}
파일 1개가 저장되면, files collection 에는 1개의 row가 입력됩니다.
chunksTop
files collection 과 1:n 으로 관계지어지는 collection 입니다.
{"_id" : <unspecified>, // object id of the chunk in the _chunks collection"files_id" : <unspecified>, // 일명 files.id FK 라고 생각하면 됩니다."n" : chunk_number, // 256k 단위 chunk의 순번입니다. (예) 1,2,3"data" : data_binary, // BSON binary 형태의 데이타입니다.}
files.id와 chunks.filesid 는 FK 형식으로 이어지는 구조입니다.
사용용도Top
제가 사용한 경우는 PostgreSQL 의 각종 로그정보를 Report (html)으로 자세하게 받아볼 수 있는 pgfouine을 사용하는 과정에서 이 데이타를 API 형식으로 확인하는 프로젝트에서 이용되었습니다.
API형식은 http://host/{hostname}/{date} 으로 되어 있어서, 수천대의 서버의 자세한 로그정보를 손쉽게 꺼내어 확인할 수 있었습니다.
Utility mongofilesTop
MongoDB 설치경로의 bin 디렉토리에 mongofiles 라는 명령어가 있습니다. 이것은 GridFS 에 간단하게 저장 및 삭제, 검색, 목록 등 많은 명령을 할 수 있는 도구입니다.
helpTop
$ mongofiles -hERROR: required parameter is missing in 'host'usage: mongofiles [options] command [gridfs filename]command:one of (list|search|put|get)list - list all files. 'gridfs filename' is an optional prefixwhich listed filenames must begin with.search - search all files. 'gridfs filename' is a substringwhich listed filenames must contain.put - add a file with filename 'gridfs filename'get - get a file with filename 'gridfs filename'delete - delete all files with filename 'gridfs filename'options:--help produce help message-v [ --verbose ] be more verbose (include multiple times for moreverbosity e.g. -vvvvv)--version print the program's version and exit-h [ --host ] arg mongo host to connect to ( <set name>/s1,s2 for sets)--port arg server port. Can also use --host hostname:port--ipv6 enable IPv6 support (disabled by default)-u [ --username ] arg username-p [ --password ] arg password--dbpath arg directly access mongod database files in the givenpath, instead of connecting to a mongod server -needs to lock the data directory, so cannot be usedif a mongod is currently accessing the same path--directoryperdb if dbpath specified, each db is in a separatedirectory--journal enable journaling-d [ --db ] arg database to use-c [ --collection ] arg collection to use (some commands)-l [ --local ] arg local filename for put|get (default is to use thesame name as 'gridfs filename')-t [ --type ] arg MIME type for put (default is to omit)-r [ --replace ] Remove other files with same name after PUT
TESTTop
// 파일을 생성합니다.$ echo "Hello World" > testfile.txt// testfile.txt를 GridFS에 입력합니다.[root@nodejs:~]# mongofiles put testfile.txtconnected to: 127.0.0.1added file: { _id: ObjectId('501a6bba8714e1003494b283'), filename: "testfile.txt", chunkSize: 262144, uploadDate: new Date(1343908794415), md5: "e59ff97941044f85df5297e1c302d260", length: 12 }done!// GridFS에 저장되어 있는 파일 목록을 확인합니다.$ mongofiles listconnected to: 127.0.0.1testfile.txt 12// 로컬에 저장되어 있는 testfile.txt 를 삭제합니다.$ rm testfile.txtrm: remove 일반 파일 `testfile.txt'? y// 다시 해당 파일을 GridFS 으로부터 다운로드 하여 복구합니다.[root@nodejs:~]# mongofiles get testfile.txtconnected to: 127.0.0.1done write to: testfile.txt// 다운로드된 파일을 확인합니다.[root@nodejs:~]# cat testfile.txtHello World
Collection 확인Top
위의 TEST 과정을 거치면 자동으로 fs.files, fs.chunks collection이 생성됩니다.
$ mongoMongoDB shell version: 2.0.2connecting to: test> use testswitched to db test> show collectionsfs.chunks // 확인!fs.files // 확인!system.indexes
그럼 collections 의 데이타를 확인해보겠습니다.
# 이건가?> fs.files.find()Thu Aug 2 21:11:46 ReferenceError: fs is not defined (shell):1# 역시 에러네요. 오랜만에 mongodb를 ㅋㅋ 다시한번# testfile.txt의 정보를 확인할 수 있습니다.> db.fs.files.find(){ "_id" : ObjectId("501a6bba8714e1003494b283"), "filename" : "testfile.txt", "chunkSize" : 262144, "uploadDate" : ISODate("2012-08-02T11:59:54.415Z"), "md5" : "e59ff97941044f85df5297e1c302d260", "length" : 12 }# n이 0부터 시작되고, data는 바이너리형태인것을 확인합니다.# 그리고, files_id 는 ObjectId 형식으로 동일한 내용인것을 알 수 있습니다.> db.fs.chunks.find(){ "_id" : ObjectId("501a6bba7e0a7ee0226fb956"), "files_id" : ObjectId("501a6bba8714e1003494b283"), "n" : 0, "data" : BinData(0,"SGVsbG8gV29ybGQK") }
추가로 Python 에서 사용했던 소스Top
pymongo installationTop
python에서는 pymongo 를 추천합니다.
$ easy_install pymongoSearching for pymongoReading http://cheeseshop.python.org/pypi/pymongo/Reading http://github.com/mongodb/mongo-python-driverReading http://cheeseshop.python.org/pypi/pymongo/2.2.1Best match: pymongo 2.2.1Downloading http://pypi.python.org/packages/source/p/pymongo/pymongo-2.2.1.tar.gz#md5=b9e9f844208971f42862d5a205cab1c7Processing pymongo-2.2.1.tar.gzRunning pymongo-2.2.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-vTfsvW/pymongo-2.2.1/egg-dist-tmp-uib8Bszip_safe flag not set; analyzing archive contents...Adding pymongo 2.2.1 to easy-install.pth fileInstalled /usr/lib/python2.4/site-packages/pymongo-2.2.1-py2.4-linux-x86_64.eggProcessing dependencies for pymongo
대략 이런 클래스Top
pgfouine 작업할 때 작성한 클래스입니다. 참고하세요.
!/usr/bin/env python# -*- coding: utf-8 -*-'''* MongoGridFS Wrapper** @author nanhapark'''# pymongofrom pymongo.connection import Connectionfrom pymongo.objectid import ObjectIdfrom gridfs import GridFS# utilimport typesclass MongoGridFS:def __init__(self): passdef connect(self, host, port):if isinstance(port, types.StringType) == True:port = int(port)self.instanceConnection = Connection(host, port)def setDB(self, dbname):self.db = self.instanceConnection[dbname]def setGridFS(self, prefix = 'fs'):self.fs = GridFS(self.db, prefix)def put(self, data, **kwargs):self.fs.put(data, **kwargs)def get(self, filename):out = self.fs.get_last_version(filename)return out.read()def main():# 객체생성o = MongoGridFS()# 접속o.connect('localhost', 27017)# db connecto.setDB('test')# GridFS 객체 생성o.setGridFS()# hello.txt 파일등록o.put('hello.txt', filename="hello.txt")# 가져오기ret = o.get('hello.txt')print retif __name__ == '__main__':main()
결론Top
pgfouine 프로젝트시에 어떻게 하면 html을 쉽게 저장 / 분산할 수 있을까 생각하다가, Mongodb GridFS를 알게 되었는데, 거창한 FileSystem 보다는 훨씬 심플하고 장난감(?) 같은 느낌이랄까요? 그럼 이만 감사합니다. KIN플하세요. ~~~
출처 - http://nodeqa.com/extend_ref/2#toc-top