Aquasar
  • Home
  • Portfolio
  • Articles
  • Pricing
  • About
  • Contact
WEB DEVELOPMENT |SEO |DIGITAL ADS

Updating a Review in a Database

Oct 7th, 2019

Alex Quasar

mongo

Let's say you want to implement something like Google Reviews in your web App where a user can leave a review for something. Of course, you want to make sure that only the logged in user can edit this and that the user who created the review can be the only one to edit it right?

For this simple review system, the user can only change or make a review with a review rating and a review description.

1. using an auth middleware for our protected routes.

2. For full validation you should findById first, than validate, than update and then save to the database like so.

// Name         :   Update Review
// Type         :   PATCH
// Route        :   api/reviews/:reviewId
// Description  :   Update the review, note we are using reviewId
// Access       :   Only review author can update.
router.patch('/:reviewId', auth, async (req, res, next) => {
    try {
        const { rating, description } = req.body; 
        const review = await Review.findByIdAndUpdate(req.params.reviewId);
        
        // verify user
        if(review.user.toString() !== req.user.id.toString()) return next (new AppError(`Sorry, you cannot edit this review`,403));

        // update and save review
        review.rating = rating;
        review.description = description;
        review.save();

        // return review
        res.json(review);
    } catch (error) {
        console.error(error);
        next (new AppError(`${error}`,500));
    }
}) 

In summary, before we update a review, we want to compare the logged in user id to the review author user id. Then we update the rating and review using the user inputs from the req.body.

However, while this works, update method in mongoose is more efficient than find followed by save. To do this we can use findOneAndUpdate method and pass in two criteria, the _id and and user like so:

// Name         :   Update Review
// Type         :   PATCH
// Route        :   api/reviews/:reviewId
// Description  :   Update the review, note we are using reviewId
// Access       :   Only review author can update.
router.patch('/:reviewId', auth, async (req, res, next) => {
    try {
        const { rating, description } = req.body; 
        const review = await Review.findOneAndUpdate(
            {
                _id: req.params.reviewId,
                user: req.user.id.toString(),
            },
            {
                rating,
                description
            },
            {
                new:true,
                runValidators:true
            }
        )

        // return review
        res.json(review);
    } catch (error) {
        console.error(error);
        next (new AppError(`${error}`,500));
    }
})

The req.body we only extracted the fields needed. This is more of a security measure so that user cannot change any extra form fields if there was any on the front end. The second method is actually simpler with less code and more efficient.