MongoDB Data Modeling - Embedded Documents
In the previous article we talked about how to make a reference from one document to another. References are great and should make sense to anyone who understands relational databases, but one of the best things in MongoDB is the ability to forget about references and create databases that have zero normalization. This ability comes from the use of Embedded documents—one of the truly awesome features of MongoDB.
Up until now, our documents have looked pretty lame. Something like this:
{ "_id" : ObjectId("541e99d7f5e52579d9d7b625"), "title" : "number 14", "body" : "Page Body Number 14" }
But we can make more serious documents than that. In fact, MongoDB supports a large number of data types. Let’s consider an example we used in a previous article, pages that each have a comment. We can, if we like, create the document of the comment inside of the document of the page! In other words, kind of a sub-document!
Sound confusing? Not at all! Just have a gander at this example:
db.pages.insert({
"title": "Page Title",
"body": "Page Body",
"comments": [
{
"comment_title": "Comment Number 1",
"comment_body": "Comment Number 1"
}, {
"comment_title": "Comment Number 2",
"comment_body": "Comment Number 2"
}
]
})
Here I’m creating a page that has two documents. How does it look?
> db.pages.find({
"_id": ObjectId("541ead1ef5e52579d9d7b681")
})
{
"_id": ObjectId("541ead1ef5e52579d9d7b681"),
"title": "Page Title",
"body": "Page Body",
"comments": [{
"comment_title": "Comment Number 1",
"comment_body": "Comment Number 1"
}, {
"comment_title": "Comment Number 2",
"comment_body": "Comment Number 2"
}]
}
If we want to update the comment (add or erase) we can do this in several ways—just like any normal value. It’s just that the update will be a bit more complex. And the retrieval? Just like a normal one—we get the entire object. This is the primary power behind MongDB—the schema is completely flexible and we can create complex and non-normalized documents to our desire.
If we want to run a query by way of a property that exists in the sub-document, nothing could be easier. For example, a search query that looks for Comment Number 1 will look like this:
db.pages.find({"comments.comment_title":"Comment Number 1"})
Notice that the JavaScript syntax here is playing a role. First off the main property, comments, and then then secondary property, comment_title. And what’s separating them? A dot, just like in JavaScript.
And the result? Well it’s the entire object, obviously.
So when should we use this model? This model works particularly well when making calls. The call will be executed quickly and will return all the data that we need. If we can say with certainty that we’ll always want the comment with the page, and that comments will never exist without a page, then using Embedded Documents is a good idea.
However, when we do use Embedded Documents, we lose precious time regarding writing to the database. This is because each write ‘locks’ the document, and if we have several writes this means we’ll have a performance issue. So, is there a definite answers for whether to use Embedded Documents or not? In a word, no—it’s all according to the nature of the application. Sometimes using references will be the right choice and sometimes Embedded Documents will be preferable. In MongsDB’s official documentation there are a few design patterns that are worth taking a look at, in case you’re debating which to use.
About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment