Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb Relationship: Posts and Comments (ref v sub-documents)

I know there are a lot of similar questions, but they're too old and since Mongodb has evolved alot for last 5-6 years I am looking for a good schema design.

Goal: I want to have a post with comments by users.

What I have designed so far is:

  • Separate post model:
const projectSchema = new mongoose.Schema({
    user: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
    title: { type: String, required: true },
    image: { type: String, default: undefined },
    description: { type: String, required: true, minLength: 200, maxlength: 500 },
    comments: [{
        type: mongoose.Schema.Types.ObjectId, ref: 'Comment'
    }],
    state: { type: Boolean, default: true },
    collaborators: { type: Array, default: [] },
    likes: { type: Array, default: [] }
})
  • And a separate comments model:
const commentSchema = new mongoose.Schema({
    comment: { type: String, required: true },
    project: { type: String, required: true, ref: 'Project' },
    user: { type: String, required: true, ref: 'User' }
})

The reason I am going for the relational approach is because if the comments increase to say 10,000 in number, it will increase the size of schema by alot.

This way, no matter how many comments we can populate them using their IDs, also, we will have different collection for comments iself.

Reference : one-to-many

Is this a good approach for my project?


The way I am querying the comments from one single post:

const project = await Project.findById(
        new mongoose.Types.ObjectId(req.params.projectId)
    ).populate({
        path: 'comments',
        populate: { path: 'user' }
    }).lean()
like image 637
Karan Kumar Avatar asked Feb 21 '26 15:02

Karan Kumar


1 Answers

Whether it's a good design depends how many comments per post do you expect, and what query will be performed on your app.

There's a good blog from mongodb.com on how to design your database schema

The common design is:

  • One to Few (Use embed)
  • One to Many (Use embed reference)
  • One to squillions (The usual relational database one-to-many approach)

Summary is:

So, even at this basic level, there is more to think about when designing a MongoDB schema than when designing a comparable relational schema. You need to consider two factors:

  • Will the entities on the “N” side of the One-to-N ever need to stand alone?
  • What is the cardinality of the relationship: is it one-to-few; one-to-many; or one-to-squillions?

Based on these factors, you can pick one of the three basic One-to-N schema designs:

  • Embed the N side if the cardinality is one-to-few and there is no need to access the embedded object outside the context of the parent object
  • Use an array of references to the N-side objects if the cardinality is one-to-many or if the N-side objects should stand alone for any reasons
  • Use a reference to the One-side in the N-side objects if the cardinality is one-to-squillions

There is also a blog about advanced schema design which is worth the read.


You seems to be using the two-way referencing approach.

The difference between yours and one-to-squillions is you are not only storing post id reference on comment document, but also storing comment ids as reference in post document, while one-to-squillions will only stores project id reference in comment document.

Using your approach will be better if you need to get comment ids of a post. But the disadvantage is you need to run two queries when deleting or creating a comment, one to delete / create comment id from post, and the other one to delete / create the comment document it self. It's also will be slower to find "which post belongs to given comment id".

While using one-to-squillions would gives you worse performance when performing a query to get comments by post id. But you can mitigate this by properly indexing your comment collection.

like image 162
Owl Avatar answered Feb 24 '26 16:02

Owl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!