Mongoose关联存储异常:评论对象存入营地数组而非ObjectId求助
Hey there! I can spot exactly what's throwing your data sync off—you're pushing the full comment object into the campground's comments array instead of just its ObjectId. Let's get this fixed so your updates and deletions work across both collections.
The Root Problem
Your Campground schema clearly defines the comments field as an array of ObjectIds that reference the Comment model:
comments: [ { type: mongoose.Schema.Types.ObjectId, ref: "Comment" } ]
But in your POST route, you're pushing the entire createdComment document into this array:
foundCampground.comments.push(createdComment);
Mongoose doesn't automatically extract the ObjectId from the full object here, so it stores the entire comment instead of just the reference ID. That's why changes to comments only affect the Comment collection, not the linked Campground data.
The Simple Fix
Instead of pushing the whole comment object, push only its _id property. Here's the corrected POST route code:
router.post("/", middleware.isLoggedIn, function(req, res) { Comment.create(req.body.comment, function(err, createdComment) { if(err) { console.log(err); req.flash("error", "Failed to create comment"); return res.redirect("back"); } // Set author info and save the comment createdComment.author.id = req.user._id; createdComment.author.username = req.user.username; createdComment.save(function(err) { if(err) { console.log(err); return res.redirect("back"); } // Find the campground and add ONLY the comment's ObjectId Campground.findById(req.params.id, function(err, foundCampground){ if(err) { console.log(err); req.flash("error", "Could not find campground"); return res.redirect("back"); } foundCampground.comments.push(createdComment._id); foundCampground.save(function(err) { if(err) { console.log(err); } else { req.flash("success" , "Comment created successfully"); res.redirect("/index/" + req.params.id); } }); }); }); }); });
Key Adjustments:
- Removed unnecessary
.populate("comments")from the Campground lookup—you don't need to load all comments just to add a new reference ID - Changed
foundCampground.comments.push(createdComment)tofoundCampground.comments.push(createdComment._id) - Added extra error handling to catch issues at each step (always saves headaches later!)
Bonus: Syncing Comment Deletions
Now that your associations use ObjectIds, you'll want to update the campground when a comment is deleted. Add this logic to your comment deletion route using Mongoose's $pull operator to remove the reference ID:
router.delete("/:commentId", middleware.checkCommentOwnership, function(req, res) { // Delete the comment from the Comment collection Comment.findByIdAndRemove(req.params.commentId, function(err) { if(err) { req.flash("error", "Failed to delete comment"); return res.redirect("back"); } // Remove the comment's ID from the campground's comments array Campground.findByIdAndUpdate( req.params.id, { $pull: { comments: req.params.commentId } }, function(err) { if(err) { console.log(err); } req.flash("success", "Comment deleted"); res.redirect("/index/" + req.params.id); } ); }); });
This ensures deleting a comment removes it from both collections, keeping your data perfectly in sync.
内容的提问来源于stack exchange,提问作者Blackdeath

