删除评论功能异常: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是最初查询到的旧数据(包含未删除的评论),这会将数据库中的数据还原为更新前的状态,导致删除操作失效。
修复步骤
移除多余的
product.save()调用
删除代码中的await product.save()语句,保留findByIdAndUpdate的更新逻辑即可,该方法会直接将修改后的内容写入数据库。可选优化:使用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
相关产品推荐
相关产品推荐

