CRUD Operations

Query

There are two ways to query a collection : Getting raw data or Getting Document instance .

Getting raw data

Getting raw data is useful when you only want to have one value from your data. This is fast as there’s no validation or wrapping. There are four methods to query raw data : find() and find_one(), one() and find_random().

find() and find_one()

find(), and find_one() act like the similar pymongo‘s methods. Please, see the pymongo documentation.

one()

one() acts like find() but will raise a mongokit.MultipleResultsFound exception if there is more than one result.

>>># Python 3
>>> bp2 = tutorial.BlogPost()
>>> bp2['title'] = 'my second blog post'
>>> bp2['author'] = 'you'
>>> bp2.save()

>>> tutorial.one()
Traceback (most recent call last):
...
MultipleResultsFound: 2 results found

>>> tutorial.one({'title':'my first blog post'})
{'body': None, 'author': myself', 'title': 'my first blog post', 'rank': 0, '_id': ObjectId('4b5ec4b690bce73814000000'), 'date_creation': datetime.datetime(2010, 1, 26, 10, 32, 22, 497000)}

>>> # Python 2
>>> bp2 = tutorial.BlogPost()
>>> bp2['title'] = u'my second blog post'
>>> bp2['author'] = u'you'
>>> bp2.save()

>>> tutorial.one()
Traceback (most recent call last):
...
MultipleResultsFound: 2 results found

>>> tutorial.one({'title':'my first blog post'})
{u'body': None, u'author': u'myself', u'title': u'my first blog post', u'rank': 0, u'_id': ObjectId('4b5ec4b690bce73814000000'), u'date_creation': datetime.datetime(2010, 1, 26, 10, 32, 22, 497000)}

If no document is found, one() returns ^^None^^

find_random()

find_random() will return a random document from the database. This method doesn’t take any arguments.

Getting Document instance

There are 5 methods to query your data which return ^^Document^^ instances: find(), find_one(), one(), fetch(), fetch_one() and find_random(). find() and fetch() return a cursor of collection. A cursor is a container which lazily evaluates the results. A cursor is acting like an iterator. find_one(),`one()` and fetch_one() return the document itself.

All these methods can take a query as an argument. A query is a simple dict. Check the mongodb and the pymongo documentation for further details.

find()

find() without an argument will return a cursor of all documents from the collection. If a query is passed, it will return a cursor of all documents matching the query.

find() takes the same arguments as the pymongo.collection.find method.

>>> for post in tutorial.BlogPost.find():
...     print post['title']
my first blog post
my second blog post

>>> for post in tutorial.BlogPost.find({'title':'my first blog post'}):
...     print post['title']
my first blog post

find_one()

find_one() acts like find() but will return only the first document found. This method takes the same arguments as pymongo’s find_one() method. Check the pymongo documentation.

one()

one() acts like find_one() but will raise a mongokit.MultipleResultsFound exception if there is more than one result.

>>> # Python 3
>>> tutorial.BlogPost.one()
Traceback (most recent call last):
...
MultipleResultsFound: 2 results found

>>> doc = tutorial.BlogPost.one({'title':'my first blog post'})
>>> doc
{'body': None, 'title': 'my first blog post', 'author': 'myself', 'rank': 0, '_id': ObjectId('4b5ec4b690bce73814000000'), 'date_creation': datetime.datetime(2010, 1, 26, 10, 32, 22, 497000)}
>>> isinstance(doc, BlogPost)
True

>>> # Python 2
>>> tutorial.BlogPost.one()
Traceback (most recent call last):
...
MultipleResultsFound: 2 results found

>>> doc = tutorial.BlogPost.one({'title':'my first blog post'})
>>> doc
{u'body': None, u'title': u'my first blog post', u'author': u'myself', u'rank': 0, u'_id': ObjectId('4b5ec4b690bce73814000000'), u'date_creation': datetime.datetime(2010, 1, 26, 10, 32, 22, 497000)}
>>> isinstance(doc, BlogPost)
True

If no document is found, one() returns None

fetch()

Unlike find(), fetch() will return only documents which match the structure of the Document.

>>> all_blog_posts = tutorial.BlogPost.fetch()

This will return only all blog post (which have ‘title’, ‘body’, ‘author’, ‘date_creation’, ‘rank’ as fields). This is an helper for :

>>> all_blog_posts = tutorial.BlogPost.find({'body': {'$exists': True}, 'title': {'$exists': True}, 'date_creation': {'$exists': True}, 'rank': {'$exists': True}, 'author': {'$exists': True}})

Note that like with find() and one(), you can pass advanced queries:

>>> my_blog_posts = tutorial.BlogPost.fetch({'author':'myself'})

which is equivalent to:

>>> all_blog_posts = tutorial.BlogPost.find({'body': {'$exists': True}, 'title': {'$exists': True}, 'date_creation': {'$exists': True}, 'rank': {'$exists': True}, 'author': 'myself'})

fetch_one()

Just like fetch() but raise a mongokit.MultipleResultsFound exception if there is more than one result.

find_random()

find_random() will return a random document from the database. This method doesn’t take other arguments.

Update

Update in Mongokit is as easy as saving an object. Just modify your document and save it:

# Python 3
@connection.register
... class MyDoc(Document):
...    structure = {
...        'foo':{
...            'bar':[str],
...            'eggs':{'spam':int},
...        },
...        'bla':str
...    }
>>> doc = self.col.MyDoc()
>>> doc['_id'] = 3
>>> doc['foo']['bar'] = ['mybar', 'yourbar']
>>> doc['foo']['eggs']['spam'] = 4
>>> doc['bla'] = 'ble'
>>> doc.save()

>>> # Let's modify our doc :
>>> doc['foo']['eggs']['spam'] = 2
>>> doc['bla']= 'bli'
>>> doc.save()
# Python 2
@connection.register
... class MyDoc(Document):
...    structure = {
...        'foo':{
...            'bar':[unicode],
...            'eggs':{'spam':int},
...        },
...        'bla':unicode
...    }
>>> doc = self.col.MyDoc()
>>> doc['_id'] = 3
>>> doc['foo']['bar'] = [u'mybar', u'yourbar']
>>> doc['foo']['eggs']['spam'] = 4
>>> doc['bla'] = u'ble'
>>> doc.save()

>>> # Let's modify our doc :
>>> doc['foo']['eggs']['spam'] = 2
>>> doc['bla']= u'bli'
>>> doc.save()

Important

You have to be aware that updating a document like that is not atomic. To do so, please read the next section.

Bulk and atomic updates

As Mongokit exposes all the pymongo API, you can use the pymongo’s update on collection:

>>> con.test.tutorial.update({'title': 'my first blog post'}, {'$set':{'title':u'my very first blog post'}})

For more information, please look at the pymongo documentation.

reload()

If a document was updated in another thread, it would be necessary to refresh the document to match changes from the database. To do that, use the reload() method.

You should know two things before using this method :

  • If no _id is set in the document, a KeyError is raised.
  • If a document is not saved into the database, the OperationFailure exception is raised.
  • using reload() will erase all unsaved values !

Example:

>>> @connection.register
... class MyDoc(Document):
...    __database__ = 'test'
...    __collection__ = 'tutorial'
...    structure = {
...        'foo':{
...            'eggs':{'spam':int},
...        },
...        'bla':unicode
...    }

>>> doc = connection.MyDoc()
# calling reload() here will raise a KeyError
>>> doc['_id'] = 3
>>> doc['foo']['eggs']['spam'] = 4
>>> doc['bla'] = u'ble'
# calling reload() here will raise an OperationFailure
>>> doc.save()
>>> doc['bla'] = u'bli' # we don't save this change this will be erased
>>> connection.test.tutorial.update({'_id':doc['_id']}, {'$set':{'foo.eggs.spam':2}})
>>> doc.reload()
>>> doc
{'_id': 3, 'foo': {u'eggs': {u'spam': 2}}, 'bla': u'ble'}

find_and_modify()

This method allows to return a Document object after or before making an update.

If you call find_and_modify on a Collection object, it will return a dict object:

>>> d = connection.test.tutorial.find_and_modify({'bla':'ble'}, {'$set':{'foo.eggs.spam':2}})
>>> isinstance(d, MyDoc)
False
>>> isinstance(d, dict)
True

If you call find_and_modify on a Document object, it will return a Document object:

>>> d = connection.MyDoc.find_and_modify({'bla':'ble'}, {'$set':{'foo.eggs.spam':2}})
>>> isinstance(d, MyDoc)
True

Please, read the mongodb documentation to learn how to use the find_and_modify method.