Skip to content
This repository has been archived by the owner on Jul 14, 2020. It is now read-only.
namlook edited this page Aug 26, 2013 · 3 revisions

GridFS

MongoKit implements GridFS support and brings some helpers to facilitate the use of relative small files.

Let's create a document Doc which have two attachment in GridFS named as source and template:

>>> from mongokit import *
>>> class Doc(Document):
...        structure = {
...            'title':unicode,
...        }
...        gridfs = {'files':['source', 'template']}

You might want to be able to add file in gridfs on the fly without knowing their name. The new API allow to add "containers" to gridfs. So, the gridfs declaration look like this:

gridfs = {
  'files':['source', 'template'],
  'containers': ['images'],
}

As you can see, nothing hard. We just declare our attachment files in the gridfs attribute. Filling this attribute will generate an fs attribute at runtime. This fs attribute is actually an object which deal with GridFS.

>>> connection = Connection()
>>> connection.register([Doc])
>>> doc = connection.test.tutorial.Doc()
>>> doc['title'] = u'Hello'
>>> doc.save()

Before using gridfs attachment, you have to save the document. This is required as under the hood, mongokit use the document _id to link with GridFS files.

The simple way

All gridfs attachments are accessible via the fs object. Now, we can fill the source and template:

>>> doc.fs.source = "Hello World !"
>>> doc.fs.template = "My pretty template"

And that's it ! By doing this, MongoKit will open a GridFile, fill it with the value, and close it.

Note that you have to be carefull to the type: attachments only accept string.

You can read any attachment in a very simple way:

>>> doc.fs.source
'Hello World !'

You can add any image you want to the container "images":

>>> doc.fs.images['image1.png'] = "..."
>>> doc.fs.images['image1.png']
'...'
>>> doc.fs.images['image2.png'] = '...'

This is very usefull when you want of store a number of file but you don't know their names.

If you do not know stored file names, you can list them by iterate:

>>> [f.name for f in doc.fs]
['source', 'template']

You can list a container as well. The container name is accessible via the container attribute:

>>> for f in doc.fs.images:
...    print '%s/%s' % (f.container, f.name)
images/image1.png
images/image2.png

The full way

While the previous method is very easy, it might not be enougth if you're dealing with very big files or want to use some file related feature (for instance, using seek to not have to load all the file in memory)

You can do that with using the get_last_version() method on the fs object.

>>> f = doc.fs.get_last_version("source")
>>> f.read(10)

If you want to create a file and write in it, you can do that with using the new_file() method on the fs object. The new_file() method take the file name and all other properties pymongo accepts here:

>>> f = doc.fs.new_file('source')
>>> f.write("Hello World again !")
>>> f.close() 

You can also use with keyword to handle write operations:

>>> with doc.fs.new_file("source") as f:
...     f.write("Hello World again !")

You can add any image you want to the container "images":

>>> f = doc.fs.images.new_file('image1.png')
>>> f.write('...')
>>> f.close()
>>> f = doc.fs.images.get_last_version('image1.png')
>>> f.read(10)

All PyMongo API is supported::

>>> id = doc.fs.put("Hello World", filename="source")
>>> doc.fs.get(id).read()
'Hello World'
>>> doc.fs.get_last_version("source")
<gridfs.grid_file.GridOut object at 0x1573610>
>>> doc.fs.get_last_version("source").read()
'Hello World'
>>> f = doc.fs.new_file("source")
>>> f.write("New Hello World!")
>>> f.close()
>>> doc.fs.source
'New Hello World!'
>>> new_id = doc.fs.get_last_version("source")._id
>>> doc.fs.delete(new_id)
>>> doc.fs.source
'Hello World'