MERN栈下如何编辑Post Schema嵌套结构中的评论?
MERN应用评论编辑功能实现指导
我正在开发一款支持用户发帖和评论的应用,基于MERN(mongoose、express、react、nodejs)技术栈。目前已成功实现评论删除功能,但不知道如何编辑Post Schema中的评论。以下是我的相关代码,请求指导正确的实现方式:
Post Schema代码
const mongoose = require('mongoose') const { ObjectId } = mongoose.Schema.Types const postSchema = new mongoose.Schema({ title: { type: String, required: true }, body: { type: String, required: true }, photo: [{ type: String, required: true }], likes: [{ type: ObjectId, ref: "User" }], comments: [{ text: String, postedBy: { type: ObjectId, ref: "User" } }], postedBy: { type: ObjectId, ref: "User" } }, { timestamps: true }) mongoose.model("Post", postSchema)
已实现的评论删除接口代码
router.delete('/deletecomment/:postId/:commentId', requireLogin, (req, res) => { Post.findOne({ _id: req.params.postId }) .populate("postedBy", "_id") .populate('comments.postedBy', '_id name') .exec((err, post) => { if (err || !post) { return res.json({ error: err }); } post.comments = post.comments.filter(item => { if (!(item.postedBy._id.toString() === req.user._id.toString() && item._id.toString() === req.params.commentId.toString())) { return item } }) post.save() .then(result => { Post.findOne({ _id: result.id }) .populate('postedBy', '_id name profilePhoto') .populate('comments.postedBy', '_id name') .exec((err, post) => { if (err || !post) { return res.json({ error: err }); } res.json({ result: post, message: 'Successfully deleted comment!' }); }) }) .catch(err => { console.error(err); }) }) });
尝试编写的评论编辑接口代码(存在问题)
router.put('/editcomment/:postId/:commentId', requireLogin, (req, res) => { const editComment = { text: req.body.text, postedBy: req.user._id } Post.findByIdAndUpdate(req.body.postId, { $set: { comments: editComment } }, { new: true }) .populate("comments.postedBy", "_id name") .populate("postedBy", "_id name") .exec((err, result) => { console.log("result => ", result) if (err) { return res.status(422).json({ error: err }) } else { res.json(result) } }) })
问题分析
当前编辑接口有几个关键问题:
- 错误替换整个评论数组:用
$set: { comments: editComment }会直接把帖子的所有评论替换成单个新对象,而非修改指定评论。 - 参数获取错误:路由参数里的
postId是req.params.postId,但代码里误用了req.body.postId,会导致找不到对应帖子。 - 缺少权限验证:未检查当前登录用户是否是该评论的发布者,存在任意用户可修改他人评论的安全隐患。
正确实现方式
方法1:使用MongoDB数组更新操作符(推荐)
利用MongoDB的$set结合位置操作符$,直接定位目标评论并更新:
router.put('/editcomment/:postId/:commentId', requireLogin, (req, res) => { const { text } = req.body; if (!text) { return res.status(422).json({ error: '评论内容不能为空' }); } Post.findByIdAndUpdate( { _id: req.params.postId, 'comments._id': req.params.commentId, 'comments.postedBy': req.user._id // 仅允许评论作者编辑 }, { $set: { 'comments.$.text': text } // 更新匹配到的评论文本 }, { new: true } // 返回更新后的文档 ) .populate('postedBy', '_id name profilePhoto') .populate('comments.postedBy', '_id name') .exec((err, updatedPost) => { if (err || !updatedPost) { return res.status(422).json({ error: err || '无法找到对应帖子/评论,或无权限编辑' }); } res.json({ result: updatedPost, message: '评论编辑成功!' }); }); });
方法2:先查询后修改(与删除逻辑一致)
先找到帖子,定位目标评论并验证权限,修改后保存:
router.put('/editcomment/:postId/:commentId', requireLogin, (req, res) => { const { text } = req.body; if (!text) { return res.status(422).json({ error: '评论内容不能为空' }); } Post.findOne({ _id: req.params.postId }) .populate('comments.postedBy', '_id name') .exec((err, post) => { if (err || !post) { return res.status(422).json({ error: err || '帖子不存在' }); } // 定位目标评论并验证权限 const targetComment = post.comments.find(comment => comment._id.toString() === req.params.commentId.toString() && comment.postedBy._id.toString() === req.user._id.toString() ); if (!targetComment) { return res.status(422).json({ error: '无权限编辑该评论或评论不存在' }); } // 更新评论内容 targetComment.text = text; post.save() .then(savedPost => { // 重新关联完整数据返回 Post.findOne({ _id: savedPost._id }) .populate('postedBy', '_id name profilePhoto') .populate('comments.postedBy', '_id name') .exec((err, finalPost) => { if (err) { return res.status(422).json({ error: err }); } res.json({ result: finalPost, message: '评论编辑成功!' }); }); }) .catch(err => { res.status(422).json({ error: err }); }); }); });
内容的提问来源于stack exchange,提问作者Jawad Uddin Khan
相关产品推荐
相关产品推荐

