So, i have been trying to make a function that deletes reviews and it just isn’t working. I narrowed it down, and it seems that the filter is not working correctly, couldn’t figure out why. Please check the code and tell me what to do:
//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
})
})
//Route
//Delete a review
router.route("/review").delete(isAuthenticatedUser,deleteReview)
Below is the database —
{
"_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
}
As you can see i tried debugging using a lot of console.log and well here is a result–
//Result
[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')
}
]
The postman is giving the result without removing the review.
2
Answers
Turns out there was extra whitespace in
reviewId
used .trim() in filter and it worked. Thanks -VLAZThe problem lies in how the
_id
is structured within each review. Specifically, the_id
field is nested within an object with the key$oid
.Here is sample code to fix that