Monguo

Overview

Monguo is an asynchronous MongoDB ORM with Motor dirver for Tornado applications.

_images/monguo.jpg https://pypip.in/v/monguo/badge.png https://pypip.in/d/monguo/badge.png

Installation

$ pip install monguo

Dependencies

Quick Start

Creating a connection

Just call Connection.connect() to create a connection. If you don’t set connection_name, it will create a connection named default. If connection with the same name has been created, it will disconnect and remove it and push this connection to the top of connections stack, otherwise it push this connection to the top of connections stack directly. It will set this connection as the default connection.

from monguo.connection import Connection
Connection.connect('db')

If you want to use replica set client, just set replica_set=True.

Connection.connect('db', replica_set=True)

You can also just create a connection only and set database later.

Connection.connect()
Connection.switch_database('db')

Defining documents

Just inherit Document or EmbeddedDocument to create your document. Take a simple Tumblelog application for example.

First import kinds of fields, Document and EmbeddedDocument.

from monguo.field import *
from monguo.document import Document, EmbeddedDocument

Then define our documents.

UserDocument

We assume UserDocument has name, email and age fields. In meta we can define the collection’s name.

class UserDocument(Document):
    name  = StringField(required=True, unique=True, max_length=20)
    email = EmailField(required=True)
    age   = IntegerField()
    sex   = StringField(
        required=True, default='male', candidate=['male', 'female'])

    meta = {
        'collection': 'user'
    }

PostDocument

A post point to an author, we can use ReferenceField to define it. And we set comments as it’s embedded document.

class PostDocument(Document):
    author       = ReferenceField(UserDocument, required=True)
    publish_time = DateTimeField(required=True)
    title        = StringField(required=True, max_length=100)
    contents     = StringField(max_length=5000)
    comments     = ListField(EmbeddedDocumentField(CommentDocument))

    meta = {
        'collection': 'post'
    }

CommentDocument

The CommentDocument will be embedded in PostDocument.

class CommentDocument(EmbeddedDocument):
    commentor = ReferenceField(UserDocument, required=True)
    contents  = StringField(required=True, max_length=200)

Insert

We insert two users Bob and Alice. Bob publishs a post, and Alice comments it.

bob_id = yield UserDocument.insert({
    'name': 'Bob',
    'email': 'bob@gmail.com',
    'age': 19
})

alice_id = yield UserDocument.insert({
    'name': 'Alice',
    'email': 'alice@gmail.com',
    'sex': 'female',
    'age': 18
})

We don’t have to set bob’s sex field since it’s default value is ‘male’, it will be set automatically.

Bob publish a post.

from bson.dbref import DBRef
from datetime import datetime

post_id = yield PostDocument.insert({
    'author': DBRef(UserDocument.meta['collection'], bob_id),
    'publish_time': datetime.now(),
    'title': 'title',
})

Update

Alice comments Bob’s post.

comment = {
    'commentor': DBRef(UserDocument.meta['collection'], alice_id),
    'contents': 'I am comments.'
}

yield PostDocument.update(
    {'_id': post_id},
    {'$push': {'comments': comment}})

Query

Monguo supports all Motor’s query methods.

user = yield UserDocument.find_one({'name': 'Bob'})
posts = yield PostDocument.find().to_list(None)

You can regard Document and your defined documents as motor.MotorCollection. It’s equal to:

collection = UserDocument.get_collection()
user = yield collection.find_one({'name': 'Bob'})

collection = PostDocument.get_collection()
posts = yield collection.find().to_list(None)

Delete

We can delete Bob from user collection.

collection = yield UserDocument.remove({'name': 'Bob'})

Defining higher API

You can define higher API in your document, take UserDocoment for example.

from tornado import gen

class UserDocument(Document):
    name  = StringField(required=True, unique=True, max_length=20)
    email = EmailField(required=True)
    age   = IntegerField()
    sex   = StringField(
        required=True, default='male', candidate=['male', 'female'])

    meta = {
        'collection': 'user'
    }

    @gen.coroutine
    def get_user_list(skip=0, limit=None):
        cursor = UserDocument.find().skip(skip)

        if limit is not None:
            assert isinstance(limit, int) and limit > 0
            cursor.limit(limit)

        user_list = yield cursor.to_list(None)
        raise gen.Return(user_list)

It’s simple to call it.

user_list = yield UserDocument.get_user_list()

You can get more in API dcouemnt.

More

Monguo has the same CURD API as Motor, you can read Motor’s document.

***
Fork me on GitHub