The goal of the comments model is to support nested comments. In MongoDB there are a couple different methods to do that. You can store each comment as an individual document and provide a link to parent objects, or you can store all comments for a thread in a single document. Either way works, but they have very different implementations and consequences.
Storing the comment tree in a single document makes it simple and fast to load from MongoDB. The drawback is that because there is not a fixed depth for comments, the entire reply structure needs to be saved when new comments are added. Also, you need to get the entire document to get any of the comments.
Storing the comments as individual documents means that you can easily look up a single document, and it is simple to save any additional comments/replies because they are single documents. However, if you want to load the entire comment tree, you have to implement a complex aggregation function or do multiple lookups to build out the tree, and these approaches are both much less efficient than loading a single document.
Because comments are read very frequently but are not created very often, a good approach is to store the nested comment/reply structure in a single MongoDB document and then update the entire structure when a new comment is added.
Listing 27.3 implements the CommentThread
and Reply
model schemas. The CommentThread
model schema is used as the root document for comments on a given object. The Reply
model schema is designed to store comments/replies added to the page or photo. Notice that the replies
field of both the Reply
and CommentThread
objects is an array of reply schema objects:
replies:[ReplySchema]
This setup allows the comments to be nested inside each other and for multiple comments to be created on the same level. Figure 27.1 shows the nested structure in an actual document stored in MongoDB.
01 var mongoose = require('mongoose'),
02 Schema = mongoose.Schema;
03 var ReplySchema = new Schema({
04 username: String,
05 subject: String,
06 timestamp: { type: Date, default: Date.now },
07 body: String,
08 replies:[ReplySchema]
09 }, { _id: true });
10 var CommentThreadSchema = new Schema({
11 title: String,
12 replies:[ReplySchema]
13 });
14 mongoose.model('Reply', ReplySchema);
15 mongoose.model('CommentThread', CommentThreadSchema);