You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
            }

        })
})

问题分析

当前编辑接口有几个关键问题:

  1. 错误替换整个评论数组:用$set: { comments: editComment }会直接把帖子的所有评论替换成单个新对象,而非修改指定评论。
  2. 参数获取错误:路由参数里的postId是req.params.postId,但代码里误用了req.body.postId,会导致找不到对应帖子。
  3. 缺少权限验证:未检查当前登录用户是否是该评论的发布者,存在任意用户可修改他人评论的安全隐患。

正确实现方式

方法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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:06:00