Previous topic

Polymorphism with MongoKit

Next topic

Using relational

This Page

>>> from mongokit import *
>>> Connection().test.tutorial.remove({})
>>> Connection().test['_mongometa'].remove({})

Delete CascadeΒΆ

MongoKit support some relationnal features like “cascade”. If you create some objects wich belongs to other, it would be boring to delete all “belonging” objects by hand.

Say we have a simple object BlogArticle :

>>> class BlogArticle(MongoDocument):
...     db_name = "test"
...     collection_name = "tutorial"
...     structure = {
...         "title":unicode,
...         "author":unicode,
...     }

And now, we want to attach an object Comment. Note that “in real life”, comments would be embed in the BlogArticle object but for this use case, let’s say that it is not possible.

>>> class Comment(MongoDocument):
...     db_name = "test"
...     collection_name = "tutorial"
...     structure = {
...        "body":unicode,
...         "author":unicode,
...         "article":unicode,
...     }
...     belongs_to = {'article': BlogArticle}

The belongs_to attribute tell mongokit that the field article will be a BlogArticle id. This way, if the BlogArticle is deleted, all comments related to this article will be deleted too.

Note that the field type must be the type of the object id.

>>> article = BlogArticle()
>>> article['_id'] = u"article1"
>>> article['title'] = u"an article"
>>> article['author'] = u"me"
>>> article.save()
{'_id': u'article1', 'title': u'an article', 'author': u'me'}

Let’s create a couple of comment:

>>> comment = Comment()
>>> comment['_id'] = "comment1"
>>> comment['body'] = u"my first comment"
>>> comment['author'] = u"god"
>>> comment['article'] = article['_id']
>>> comment.save()
{'body': u'my first comment', 'article': u'article1', '_id': 'comment1', 'author': u'god'}
>>> comment = Comment()
>>> comment['_id'] = "comment2"
>>> comment['body'] = u"my second comment"
>>> comment['author'] = u"me"
>>> comment['article'] = article['_id']
>>> comment.save()
{'body': u'my second comment', 'article': u'article1', '_id': 'comment2', 'author': u'me'}
>>> Comment.fetch({'article':article['_id']}).count()
2

Let’s delete the article now. If you want to delete all related objects, you need to pass cascade=True as argument:

>>> article.delete(cascade=True)
>>> BlogArticle.fetch().count()
0

The related comments are deleted too:

>>> Comment.fetch().count()
0

Note tha “delete cascade” work with the remove() method too:

>>> BlogArticle.remove({'_id':article['_id']}, cascade=True)

You can use autorefs with belongs_to:

>>> class DocA(MongoDocument):
...      db_name = "test"
...      collection_name = "mongokit"
...      structure = {
...          "spam":{"egg":int}
...      }
>>> class DocB(MongoDocument):
...      db_name = "test"
...      collection_name = "mongokit"
...      structure = {
...          "foo":{"bar":DocA},
...      }
...      belongs_to = {'foo.bar':DocA}
...     use_autorefs = True
>>> doca = DocA()
>>> doca['spam']['egg'] = 3
>>> doca.save()
>>> docb = DocB()
>>> docb['foo']['bar'] = doca
>>> docb.save()
>>> len(list(DocA.fetch()))
1
>>> doca.delete(cascade=True)
>>> len(list(DocA.fetch()))
0