Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedded Documents issue with MongoEngine

I am using MongoDB with Flask-MongoEngine as my ORM component to my web app.

I have structured the User document schema like so:

from ..core import db

class UserComics(db.EmbeddedDocument):
    favorites = db.SortedListField(db.StringField(), default=None)

class UserSettings(db.EmbeddedDocument):
    display_favs = db.BooleanField(default=False)
    default_cal = db.StringField(default=None)
    show_publishers = db.ListField(db.StringField(), default=None)

class UserTokens(db.EmbeddedDocument):
    refresh_token = db.StringField(default=None)
    access_token = db.StringField(default=None)
    expire_time = db.StringField(default=None)

class User(db.Document, UserMixin):
    # Save User document to this collection
    meta = {'collection': 'users_test'}

    userid = db.StringField()
    full_name = db.StringField()
    first_name = db.StringField()
    last_name = db.StringField()
    gender = db.StringField()
    birthday = db.StringField()
    email = db.EmailField()
    friends = db.ListField(db.StringField())
    date_creation = db.DateTimeField()
    last_login = db.DateTimeField()
    favorites = db.EmbeddedDocumentField(UserComics)
    settings = db.EmbeddedDocumentField(UserSettings)
    tokens = db.EmbeddedDocumentField(UserTokens)

However, When creating a new user like this (I have left out lines...):

def create_new_user(resp):
    newUser = User()
    ....
    newUser.settings.default_cal = resp['calendar']
    ....
    newUser.save()
    return

I run into this error:

AttributeError: 'NoneType' object has no attribute 'default_cal'

It seems to me that I am not using MongoEngines Embedded documents correctly but I do not know where I am going wrong.

Any help would be greatly appreciated!

like image 462
Tim Bueno Avatar asked Jul 26 '13 04:07

Tim Bueno


People also ask

How do I access an embedded document in MongoDB?

Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.

Which is better PyMongo or MongoEngine?

Both PyMongo and MongoEngine can be used to access data from a MongoDB database. However, they work in very different ways and offer different features. PyMongo is the MongoDB recommended library. It makes it easy to use MongoDB documents and maps directly to the familiar MongoDB Query Language.

What are embedded documents in MongoDB?

MongoDB provides you a cool feature which is known as Embedded or Nested Document. Embedded document or nested documents are those types of documents which contain a document inside another document.

What is document in MongoEngine?

MongoEngine defines a Document class. This is a base class whose inherited class is used to define structure and properties of collection of documents stored in MongoDB database. Each object of this subclass forms Document in Collection in database.


1 Answers

Well you just have to create an embedded document object of the particular class, and then use it with the main document class, like so:

new_user = User()
user_settings = UserSettings()
user_settings.default_cal = resp['calendar']
new_user.settings = user_settings
# more stuff
new_user.save()

Note: Creating a new object only for the main document, does not automatically create the corresponding embedded document object(s), but while reading data ofcourse the case is different.

Edit:

As tbicr mentions below, we can also do this:

settings = db.EmbeddedDocumentField(UserSettings, default=UserSettings)

while declaring the field, that way we won't need to create the object as given in the first example.

like image 94
bool.dev Avatar answered Sep 23 '22 17:09

bool.dev