Reputation: 37
In a node.js server based on express, interacting with a mongo db through mongoose, I would like to insert a 'review' on 'reviews' array only if the user(identified by his id) hasn't reviewed the product yet, otherwise, update the review previously inserted. Given the following mongo schemes:
Product:
var ProductSchema = new Schema({
ownerId: {
type: Schema.ObjectId,
required: 'Owner of recharge point required'
},
name: {
type: String,
required: 'The name is required'
},
description: {
type: String
},
reviews: {
type: [Review]
}
});
Review:
var ReviewSchema = new Schema({
reviewerId: {
type: ObjectId,
required: 'Reviewer id required',
ref: 'User' <not showed>
},
review: {
type: String
},
date: {
type: Date,
default: Date.now
}
});
That's the result I came up with, but this only insert new reviews, it doesn't update them yet. I think my solution could be improved (and simplified) a lot.
exports.review_product = function (req, res) {
const review = req.body.review;
const reviewerId = req.body.reviewerId;
const productId = req.params.productId;
Product.findOne({_id: productId}, function(error, result){
if(error) {
res.status(500).send({message: error}).end()
} else if(result){
var newReview = new Review({ reviewerId: reviewerId, review: review});
Product.findOneAndUpdate({ _id: productId, 'reviews.reviewerId': { $ne: reviewerId }},
{ $push: { 'reviews': newReview}},
function(error, found) {
if (error) {
res.status(500).send({message: error}).end()
} else if(found) {
res.status(200).send({message: 'Review succefully added.'}).end()
} else {
res.status(404).send({message: 'You already reviewed this product'}).end()
}
});
} else {
res.status(404).send({message: 'Cannot find the product to be reviewed.'}).end()
}
})
};
Upvotes: 0
Views: 134
Reputation: 1482
The best approach would be make a query with mongoose to check the product for the reviewer id before anything else. You can also make your code a bit more readable using async/await.
It would likely look something like (please note this is pseudo code):
exports.reviewProduct = async (req, res) => {
const review = req.body.review;
const reviewerId = req.body.reviewerId;
const productId = req.params.productId;
const hasReviewed = await Product.find({_id: productId, 'reviews.reviewerId': { $eq: reviewerId } )
if(hasReviewed) {
Product.findOneAndUpdate({
_id: productId,
reviews: { $elemMatch: { reviewerId: reviewerId } }
},
{ $set: {
'review.$.title': review.title,
'review.$.body': review.body
}},
{'new': true, 'safe': true, 'upsert': true})
} else {
Product.findOneAndUpdate(
{ _id: productId },
{ $push: { reviews: review } },
{safe: true, upsert: true, new : true},
(err, model) => {
console.log(err);
})
}
}
Upvotes: 1
Reputation: 121
You can use the function includes()
For example:
var array = ["a","b","c"];
console.log(array.includes("a"); //return true
console.log(array.includes("z"); //return false because is not exist
Just adapt it to your code by replacing the variable string by your object
Upvotes: 0