Basic Use¶
Document Inheritance¶
First of all, let’s see the usual ODM:
import mongoengine as db
class Address(db.EmbeddedDocument):
"""Address schema."""
street = db.StringField()
city = db.StringField()
state = db.StringField()
class User(db.Document):
"""User data schema."""
name = db.StringField()
email = db.EmailField()
address = db.EmbeddedDocumentListField(Address)
As you can see the code, this code has nothing special. And, when you serialize the instance into JSON, you will get:
{
"id": { "$oid": "5700c32a1cbd5856815051ce" },
"name": "Example Man",
"email": "test@example.com",
"address": [
{
"street": "Hello Street",
"city": "Hello City",
"state": "Hello State"
}, {
"street": "World Street",
"city": "World City",
"state": "World State"
}
]
}
And yes, we want to replace $oid
object with str
that shows
5700c32a1cbd5856815051ce
. MongoEngine enables to you do it very easily.
Let’s just inherit mongoengine_goodjson.Document
like this:
import mongoengine_goodjson as gj
import mongoengine as db
class Address(gj.EmbeddedDocument):
"""Address schema."""
street = db.StringField()
city = db.StringField()
state = db.StringField()
class User(gj.Document):
"""User data schema."""
name = db.StringField()
email = db.EmailField()
address = db.EmbeddedDocumentListField(Address)
Then, running user.to_json
(user
is the instance object of User),
you will get the JSON code like this:
{
"id": "5700c32a1cbd5856815051ce",
"name": "Example Man",
"email": "test@example.com",
"address": [
{
"street": "Hello Street",
"city": "Hello City",
"state": "Hello State"
}, {
"street": "World Street",
"city": "World City",
"state": "World State"
}
]
}
Follow Reference¶
Let’s see ODM using ReferenceField
.
import mongoengine as db
import mongoengine_goodjson as gj
class Book(gj.Document):
"""Book information model."""
name = db.StringField(required=True)
isbn = db.StringField(required=True)
author = db.StringField(required=True)
publisher = db.StringField(required=True)
publish_date = db.DateTimeField(required=True)
class User(gj.Document):
firstname = db.StringField(required=True)
lastname = db.StringField(required=True)
books_bought = db.ListField(db.ReferenceField(Book))
favorite_one = db.ReferenceField(Book)
And here is the JSON data:
{
"id": "570ee9d1fec55e755db82129",
"firstname": "James",
"lastname": "Smith",
"books_bought": [
"570eea0afec55e755db8212a",
"570eea0bfec55e755db8212b",
"570eea0bfec55e755db8212c"
],
"favorite_one": "570eea0bfec55e755db8212b"
}
This seems to be good deal for Reference Field
, but sometimes you might
want to generate the Document with Referenced Document like Embedded Document
like this:
{
"id": "570ee9d1fec55e755db82129",
"firstname": "James",
"lastname": "Smith",
"books_bought": [
{
"id": "570eea0afec55e755db8212a",
"name": "ドグラ・マグラ (上)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366035"
},
{
"id": "570eea0bfec55e755db8212b",
"name": "ドグラ・マグラ (下)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366042"
},
{
"id": "570eea0bfec55e755db8212c",
"name": "The Voynich Manuscript: Full Color Photographic Edition",
"author": "Unknown",
"publisher": "FQ Publishing",
"publish_date": "2015-01-17",
"isbn": "978-1599865553"
}
],
"favorite_one": {
"id": "570eea0bfec55e755db8212b",
"name": "ドグラ・マグラ (下)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366042"
}
}
Of course, you can generate the json document by calling to_json()
many times like this:
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
user_dct = json.loads(user.to_json())
user_dct["books"] = [
json.loads(book.to_json()) for book in user.books_bought
]
user_dct["favorite_one"] = json.loads(user.favorite_one.to_json())
return jsonify(user_dct)
# ...And what if there are references in the referenced document??
However, as you can see, that code is messy and it has a problem that causes
code-bloat. To avoid the problem, this script has a function called
Follow Reference
since version 0.9. To use it, you can just pass
follow_reference=True
to to_json
function like this:
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
return jsonify(json.loads(user.to_json(follow_reference=True)))
Note that setting follow_reference=True
, Document.to_json
checks the reference recursively until the depth reaches 3rd depth. To change
the maximum recursion depth, you can set the value you want to max_depth
:
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
return jsonify(json.loads(user.to_json(follow_reference=True, max_depth=5)))