I am creating a e-commerce app and now I want to update and delete a review of a product using nodejs and database is mongoDB (using mongoose). This is my User Schemas and Product Schema:
const userSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true, unique: true, trim: true },
password: { type: String, required: true, trim: true },
isAdmin: { type: Boolean, required: true, default: false },
},
{
timestamps: true,
}
);
const productSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
required: true,
ref: "users",
},
name: { type: String, required: true },
image: { type: String, required: true },
brand: { type: String, required: true },
category: { type: String, required: true },
description: { type: String, required: true },
reviews: [
{
name: { type: String, required: true },
rating: { type: Number, required: true },
comment: { type: String, required: true },
user: {
type: Schema.Types.ObjectId,
required: true,
ref: "users",
},
},
{
timestamps: true,
},
],
rating: { type: Number, required: true, default: 0 },
reviewNumber: { type: Number, required: true, default: 0 },
price: { type: Number, required: true, default: 0 },
countInStock: { type: Number, required: true, default: 0 },
});
I completed the create function but I don't know how to implement update and delete function, this this my create function:
//* desc Create review
//* route POST /product/:id/review
//* access Private
const createReview = async (req, res) => {
const { rating, comment } = req.body;
if (!rating || !comment) {
return res.status(400).json({
success: false,
message: "Missing infomation",
});
}
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(400).json({
success: false,
message: "Product is not found",
});
}
const review = product.reviews;
const alreadyReviewed = product.reviews.find(
(i) => i.user.toString() === req.user._id.toString()
);
if (alreadyReviewed) {
return res.status(400).json({
success: false,
message: "User have already reviewed this product",
});
}
const newReview = {
name: req.user.name,
rating: 0 || Number(rating),
comment,
user: req.user._id,
};
review.push(newReview);
product.reviewNumber = review.length;
product.rating =
review.reduce((acc, item) => item.rating acc, 0) / review.length;
await product.save();
return res.status(200).json({
success: true,
message: "Create review successfully",
product,
});
} catch (error) {
console.log(error);
return res.status(500).json({
success: false,
message: "Internal server error",
});
}
};
So how can I implement update and delete function?
CodePudding user response:
I am assuming according to your code one product can have only one review per user.
//* desc update review
//* route PUT /product/:id/review
//* access Private
const createReview = async (req, res) => {
const { rating, comment } = req.body;
if (!rating || !comment) {
return res.status(400).json({
success: false,
message: "Missing infomation",
});
}
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(400).json({
success: false,
message: "Product is not found",
});
}
const reviews = product.reviews;
const foundReviewIndex = product.reviews.findIndex(
(i) => i.user.toString() === req.user._id.toString()
);
if (foundReviewIndex === -1) {
return res.status(400).json({
success: false,
message: "Review not found",
});
}
reviews[foundReviewIndex].rating = rating ? Number(rating) : 0,
reviews[foundReviewIndex].comment = comment,
product.rating =
review.reduce((acc, item) => item.rating acc, 0) / review.length;
await product.save();
return res.status(200).json({
success: true,
message: "Updated review successfully",
product,
});
} catch (error) {
console.log(error);
return res.status(500).json({
success: false,
message: "Internal server error",
});
}
};
Similarly, you can write a function for deleting a review. I suggest you create a separate collection for reviews and keep both product and user references in the review schema.
CodePudding user response:
I've created a sample route. Obviously you can change the route acc. to your needs, and pass in the necessary parameters.
I've used $pull
operator to delete the review from a product using userId
app.delete("/deleteReview/:productId/:userId", async (req, res) => {
try {
// userId could also be from your middleware so you can change it here.
const { productId, userId } = req.params;
const product = await ProductModel.findOneAndUpdate(
{ _id: productId },
{ $pull: { reviews: { user: userId } } },
{ new: true }
);
res.json(product);
} catch (error) {
console.error(error);
return res.status(500).send(`Server error`);
}
});
Regarding updating review, I want to know whether you're going to update review using reviewId or userId? I'll update the answer acc. to your answer.