I've worked exclusively with RDBMSs for the past 10 years and am trying to explore something new to me like MongoDB. I’m trying to learn about data model design in this environment and because normalization is so engrained in my brain, it feels weird to denormalize and know how and when to do it. A number of questions are coming to mind:

  • What is Mongo’s answer for modeling a one-to-many relationship?
  • What is Mongo’s answer for modeling many-to-many relationships?
  • So, if I have a users collections and a comments collection, where as user has many comments, and a comment references the user document, how do we join this data functionally in code? For each comment displayed, do we “query” the users collection to retrieve their associated username? Or do we embed that user’s username directly into the comments and then push an update to the embedded username in comments in the event that the user’s username would change?
  • How do we make a decision about when to embed information versus creating a new collection?



I agree with Markus W Mahlberg that this a very broad question and I am looking forward to read his blog. In my answer below I providing a few guidelines that should provide you with a good starting point when designing your data models.

As as a rule of thumb you should favour embedding, unless you need to regularly query the embedded objects on its own or if the embedded array is likely to get too large(>~100 records). Don't worry about the overhead of joins when splitting up a document into multiple collections as application-level joins are generally comparable in speed compared to a server-side join in a relational database provided your collections are properly indexed.

When normalising you should also take in consideration the write/read ratio of your data. A field that will mostly be read and only rarely updated is a good candidate for denormalisation. If you denormalise a field that is updated frequently then the extra work of finding and updating all the instances is likely to outweigh the savings that obtained from denormalising.

Looking at your particular case, you are probably better off splitting users and comments in separate collections unless you do not allow users to change their username. You could store the ObjectId of a user in the comments collection to link the two collections. You can then use an application-level join like the one below. In this example query the the 10 most recent comments for that particular user are returned:

 // Fetch the user documents identified by this user_name
> user = db.users.findOne({user_name: "john doe"});// assumes unique index
   // Fetch all the comments that are linked to this user
> comments = db.comments.find({_id: user._id  }).sort({CreatedAtUtc : -1}).limit(5000).toArray() ;
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy