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 -h
ERROR: 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 prefix
which listed filenames must begin with.
search - search all files. 'gridfs filename' is a substring
which 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 more
verbosity 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 given
path, instead of connecting to a mongod server -
needs to lock the data directory, so cannot be used
if a mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate
directory
--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 the
same 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.txt
connected to: 127.0.0.1
added file: { _id: ObjectId('501a6bba8714e1003494b283'), filename: "testfile.txt", chunkSize: 262144, uploadDate: new Date(1343908794415), md5: "e59ff97941044f85df5297e1c302d260", length: 12 }
done!
// GridFS에 저장되어 있는 파일 목록을 확인합니다.
$ mongofiles list
connected to: 127.0.0.1
testfile.txt 12
// 로컬에 저장되어 있는 testfile.txt 를 삭제합니다.
$ rm testfile.txt
rm: remove 일반 파일 `testfile.txt'? y
// 다시 해당 파일을 GridFS 으로부터 다운로드 하여 복구합니다.
[root@nodejs:~]# mongofiles get testfile.txt
connected to: 127.0.0.1
done write to: testfile.txt
// 다운로드된 파일을 확인합니다.
[root@nodejs:~]# cat testfile.txt
Hello World
Collection 확인Top
위의 TEST 과정을 거치면 자동으로 fs.files, fs.chunks collection이 생성됩니다.
$ mongo
MongoDB shell version: 2.0.2
connecting to: test
> use test
switched to db test
> show collections
fs.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 pymongo
Searching for pymongo
Reading http://cheeseshop.python.org/pypi/pymongo/
Reading http://github.com/mongodb/mongo-python-driver
Reading http://cheeseshop.python.org/pypi/pymongo/2.2.1
Best match: pymongo 2.2.1
Downloading http://pypi.python.org/packages/source/p/pymongo/pymongo-2.2.1.tar.gz#md5=b9e9f844208971f42862d5a205cab1c7
Processing pymongo-2.2.1.tar.gz
Running pymongo-2.2.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-vTfsvW/pymongo-2.2.1/egg-dist-tmp-uib8Bs
zip_safe flag not set; analyzing archive contents...
Adding pymongo 2.2.1 to easy-install.pth file
Installed /usr/lib/python2.4/site-packages/pymongo-2.2.1-py2.4-linux-x86_64.egg
Processing dependencies for pymongo
대략 이런 클래스Top
pgfouine 작업할 때 작성한 클래스입니다. 참고하세요.
!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
* MongoGridFS Wrapper
*
* @author nanhapark
'''
# pymongo
from pymongo.connection import Connection
from pymongo.objectid import ObjectId
from gridfs import GridFS
# util
import types
class MongoGridFS:
def __init__(self): pass
def 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 connect
o.setDB('test')
# GridFS 객체 생성
o.setGridFS()
# hello.txt 파일등록
o.put('hello.txt', filename="hello.txt")
# 가져오기
ret = o.get('hello.txt')
print ret
if __name__ == '__main__':
main()
결론Top
pgfouine 프로젝트시에 어떻게 하면 html을 쉽게 저장 / 분산할 수 있을까 생각하다가, Mongodb GridFS를 알게 되었는데, 거창한 FileSystem 보다는 훨씬 심플하고 장난감(?) 같은 느낌이랄까요? 그럼 이만 감사합니다. KIN플하세요. ~~~
출처 - http://nodeqa.com/extend_ref/2#toc-top