Modeling

AIOMotorEngine uses the concept of models to interact with MongoDB. To create a model we inherit from the Document class:

Let’s say we need an article model with title, description and published_date:

from aiomotorengine.document import Document
from aiomotorengine.fields import StringField, DateTimeField

class Article(Document):
    title = StringField(required=True)
    description = StringField(required=True)
    published_date = DateTimeField(auto_now_on_insert=True)

That allows us to create, update, query and remove articles with extreme ease:

new_title = "Better Title %s" % uuid4()

async def crud_article():
    article = await Article.objects.create(
        title="Some Article",
        description="This is an article that really matters."
    )

    article.title = new_title
    await article.save()

    articles = await Article.objects.filter(title=new_title).find_all()

    assert len(articles) == 1
    assert articles[0].title == new_title

    number_of_deleted_items = await articles[0].delete()

    assert number_of_deleted_items == 1

io_loop.run_until_complete(crud_article())

Base Field

class aiomotorengine.fields.base_field.BaseField(db_field=None, default=None, required=False, on_save=None, unique=None)[source]

This class is the base to all fields. This is not supposed to be used directly in documents.

Available arguments:

  • db_field - The name this field will have when sent to MongoDB
  • default - The default value (or callable) that will be used when first creating an instance that has no value set for the field
  • required - Indicates that if the field value evaluates to empty (using the is_empty method) a validation error is raised
  • on_save - A function of the form lambda doc, creating that is called right before sending the document to the DB.
  • unique - Indicates whether an unique index should be created for this field.

To create a new field, four methods can be overwritten:

  • is_empty - Indicates that the field is empty (the default is comparing the value to None);
  • validate - Returns if the specified value for the field is valid;
  • to_son - Converts the value to the BSON representation required by motor;
  • from_son - Parses the value from the BSON representation returned from motor.

Available Fields

class aiomotorengine.fields.string_field.StringField(max_length=None, *args, **kw)[source]

Field responsible for storing text.

Usage:

name = StringField(required=True, max_length=255)

Available arguments (apart from those in BaseField):

  • max_length - Raises a validation error if the string being stored exceeds the number of characters specified by this parameter
class aiomotorengine.fields.datetime_field.DateTimeField(auto_now_on_insert=False, auto_now_on_update=False, *args, **kw)[source]

Field responsible for storing dates.

Usage:

date = DateTimeField(required=True, auto_now_on_insert=True, auto_now_on_update=True)

Available arguments (apart from those in BaseField):

  • auto_now_on_insert - When an instance is created sets the field to datetime.now()
  • auto_now_on_update - Whenever the instance is saved the field value gets updated to datetime.now()
class aiomotorengine.fields.uuid_field.UUIDField(db_field=None, default=None, required=False, on_save=None, unique=None)[source]

Field responsible for storing uuid.UUID.

Usage:

name = UUIDField(required=True)
class aiomotorengine.fields.boolean_field.BooleanField(*args, **kw)[source]

Field responsible for storing boolean values (bool()).

Usage:

isActive = BooleanField(required=True)

BooleanField has no additional arguments available (apart from those in BaseField).

Multiple Value Fields

class aiomotorengine.fields.list_field.ListField(base_field=None, *args, **kw)[source]

Field responsible for storing list.

Usage:

posts = ListField(StringField())

Available arguments (apart from those in BaseField):

  • base_field - ListField must be another field that describe the items in this list

Embedding vs Referencing

Embedding is very useful to improve the retrieval of data from MongoDB. When you have sub-documents that will always be used when retrieving a document (i.e.: comments in a post), it’s useful to have them be embedded in the parent document.

On the other hand, if you need a connection to the current document that won’t be used in the main use cases for that document, it’s a good practice to use a Reference Field. MotorEngine will only load the referenced field if you explicitly ask it to, or if you set __lazy__ to False.

GeoJson Fields