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

删除评论功能异常:Filter未过滤指定ID的评论求助

商品评论删除功能故障排查与修复

问题描述

开发商品评论删除功能时,指定ID的评论无法被移除。经调试发现,filter逻辑执行后评论数组未发生预期变化,最终数据库中的评论也未被删除。

控制器代码

//Delete review
exports.deleteReview=catchAsyncErrors(async(req,res,next)=>{
    //Find product by its Id
    const product=await Product.findById(req.query.productId);
    const reviewId=req.query.id.toString()

    if(!product){
        return next(new ErrorHandler("Product not Found!",400))
    }
    console.log('Review ID (from query):', reviewId);
    console.log('Existing reviews:', product.reviews);

    //Filter out the reviews by its _id
    const updatedReviews = product.reviews.filter(rev => {
        console.log('Review ID:', rev._id.toString(), '==', reviewId);
        return rev._id.toString() !== reviewId;
    });
    console.log('Updated reviews:', updatedReviews);

    //if the filter didn't work or invalid id

    if (updatedReviews.length === product.reviews.length) {
        return next(new ErrorHandler("Review not found. Invalid review ID", 400));
    }

    //Calculate the rating and new numofReviews
    let avg=0;
    if (updatedReviews.length > 0) {
        updatedReviews.forEach(rev => {
            avg += rev.rating;
        });
        avg /= updatedReviews.length;
    }

    //Update the product with new reviews,ratings and numOfReviews
    const updatedProduct=await Product.findByIdAndUpdate(req.query.productId,{
        reviews:updatedReviews,
        ratings:avg,
        numofReviews:updatedReviews.length
    },{
        new:true,
        runValidators:true,
        useFindAndModify:false
    })

    await product.save()

    res.status(200).json({
        success:true,
        updatedProduct
    })

})

路由配置

//Delete a review
router.route("/review").delete(isAuthenticatedUser,deleteReview)

数据库文档示例

{
  "_id": {
    "$oid": "6686669d001eaace2f3cc103"
  },
  "name": "Product256",
  "description": "MSI Katana",
  "price": 200000,
  "ratings": 4.5,
  "images": [
    {
      "public_id": "Image abcde",
      "url": "SampleImageURI",
      "_id": {
        "$oid": "6686669d001eaace2f3cc104"
      }
    }
  ],
  "category": "Laptop",
  "stock": 3,
  "numofReviews": 2,
  "user": {
    "$oid": "6680fe296f7960665677f468"
  },
  "reviews": [
    {
      "user": {
        "$oid": "6680fe296f7960665677f468"
      },
      "name": "Someone1",
      "rating": 5,
      "comment": "Excellent!",
      "_id": {
        "$oid": "668684131c5010baf9c1fdf3"
      }
    },
    {
      "user": {
        "$oid": "668168d89de2122e5c13c8a9"
      },
      "name": "Someone2",
      "rating": 4,
      "comment": "uhfvkuh!",
      "_id": {
        "$oid": "6686842f1c5010baf9c1fdfa"
      }
    }
  ],
  "createdAt": {
    "$date": "2024-07-04T09:08:45.192Z"
  },
  "__v": 4
}

调试日志输出

[nodemon] restarting due to changes...
[nodemon] starting `node Backend/server.js`
Server is working on http://localhost:4000
MongoDb connected with server: 127.0.0.1
Review ID (from query): 6686842f1c5010baf9c1fdfa

Existing reviews: [
  {
    user: new ObjectId('6680fe296f7960665677f468'),
    name: 'Someone1',
    rating: 5,
    comment: 'Excellent!',
    _id: new ObjectId('668684131c5010baf9c1fdf3')
  },
  {
    user: new ObjectId('668168d89de2122e5c13c8a9'),
    name: 'Someone2',
    rating: 5,
    comment: 'Remove this!',
    _id: new ObjectId('6686842f1c5010baf9c1fdfa')
  }
]
Review ID: 668684131c5010baf9c1fdf3 == 6686842f1c5010baf9c1fdfa

Review ID: 6686842f1c5010baf9c1fdfa == 6686842f1c5010baf9c1fdfa

Updated reviews: [
  {
    user: new ObjectId('6680fe296f7960665677f468'),
    name: 'Someone1',
    rating: 5,
    comment: 'Excellent!',
    _id: new ObjectId('668684131c5010baf9c1fdf3')
  },
  {
    user: new ObjectId('668168d89de2122e5c13c8a9'),
    name: 'Someone2',
    rating: 5,
    comment: 'Remove this!',
    _id: new ObjectId('6686842f1c5010baf9c1fdfa')
  }
]

问题定位与解决方案

核心问题

代码中存在重复保存数据的逻辑:在通过findByIdAndUpdate更新数据库后,又调用了await product.save(),而product是最初查询到的旧数据(包含未删除的评论),这会将数据库中的数据还原为更新前的状态,导致删除操作失效。

修复步骤

  1. 移除多余的product.save()调用
    删除代码中的await product.save()语句,保留findByIdAndUpdate的更新逻辑即可,该方法会直接将修改后的内容写入数据库。

  2. 可选优化:使用MongoDB原生操作符提升效率
    可以不用先查询再过滤,直接用$pull操作符移除指定ID的评论,同时结合$inc和reduce更新评论数和评分,减少数据库交互次数:

    exports.deleteReview = catchAsyncErrors(async (req, res, next) => {
        const reviewId = req.query.id;
        const productId = req.query.productId;
    
        // 移除指定评论并更新评论数
        const updatedProduct = await Product.findByIdAndUpdate(
            productId,
            {
                $pull: { reviews: { _id: reviewId } },
                $inc: { numofReviews: -1 }
            },
            { new: true, runValidators: true, useFindAndModify: false }
        );
    
        if (!updatedProduct) {
            return next(new ErrorHandler("Product not Found!", 400));
        }
    
        // 检查评论是否存在
        if (updatedProduct.numofReviews < 0) {
            return next(new ErrorHandler("Review not found. Invalid review ID", 400));
        }
    
        // 重新计算评分
        let avg = 0;
        if (updatedProduct.reviews.length > 0) {
            avg = updatedProduct.reviews.reduce((sum, rev) => sum + rev.rating, 0) / updatedProduct.reviews.length;
        }
    
        // 更新评分
        await Product.findByIdAndUpdate(
            productId,
            { ratings: avg },
            { new: true, runValidators: true, useFindAndModify: false }
        );
    
        res.status(200).json({
            success: true,
            updatedProduct
        });
    });
    

验证修复

修改后重新测试,调试日志中updatedReviews应只包含剩余的评论,Postman返回的结果中目标评论会被移除,数据库中的数据也会同步更新。

内容的提问来源于stack exchange,提问作者Soumodeep

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:47:33