How to delete many relational document in MongoDB?

Viewed 454

Post collection

 Post : 
    _id : 001,
    comments : [1,2,3] // ObjectId

Comment collection

 Comment: 
    { _id : 1, message : "Bar" },
    { _id : 2, message : "Foo" },
    { _id : 3, message : "Bazz" }

I want to delete a Post and all comments on this post. But How to delete all its comments ?

Update


PostSchema

{
    model: String,
    stock: Number,
    images: [String],
    price: Number,
    views: { type: Number, default: 1 },
    commentsCount: { type: Number, default: 0 },
    comments: [{ type: Schema.Types.ObjectId, ref: "postComments" }],
    postedBy: { type: String, ref: "publisherInfo" }
  },

postComments Schema

{
    sender: String,
    createAt: { type: Date, default: Date.now },
    votes: { type: Number, default: 0 },
    contain: String
  },
2 Answers

You can use findByIdAndDelete which will delete the document and returns it. Now we can dynamically create a comment id array, and use it with deleteMany and $in operator. So we just used two db access.

router.delete("/posts/:id", async (req, res) => {
  try {
    const result = await Post.findByIdAndDelete(req.params.id);

    let commentIds = result.comments.map((c) => c._id);

    await Comment.deleteMany({
      _id: {
        $in: commentIds,
      },
    });

    res.send("OK");
  } catch (err) {
    console.log(err);
    res.status(500).send("Something went wrong");
  }
});

If the post successfully deleted but comments can't be deleted for some technical reason, you may consider using transactions so that the operations both succeeds or fails.

This way you can be safe about the query and delete all of the comments. Remove the ObjectId(id) if you already have the id in ObjectId form

const Posts = db.collection('posts')
const Comments = db.collection('collection')
const postToBeDeleted = await Posts.findOne({_id: ObjectId('posts')})
if(postToBeDeleted){
    await Posts.deleteOne({_id: ObjectId('posts')}
    for(const comment of postToBeDeleted.comments)
        await Comments.deleteOne({_id: ObjectId(comment)})
}

Related