0

I have a movie review website. I have two collections in my mongo db, one for my movie reviews, and one for reviews submitted by users.

Whenever a user submits their own review, I want to increment the variable userReviewCount within the collection of my reviews.

I'm using mongoose and running everything within javascript:

function saveUserReview(review) {

collections.ReviewModel.findOne(
    { 'filmId': review._filmId.toNumber() }, 
    function(err, result) {
        if (err) throw err;
        currentCount = result.userReviewCount;
        currentCount++;
    });

collections.ReviewModel.update(
    { 'filmId': review._filmId.toNumber() }, 
    { $set: { "userReviewCount": currentCount } }, 
    function(err, res) {
        if (err) throw err;
        console.log("Result of update:" + res);
    });  

So this function is called whenever a user submits a review. First, it uses findOne to find my review by its Id, and fetches the current value of userReviewCount. Then, it increments this by 1, and adds it back to the collection.

But what is super weird, is that the $set thing only seems to work every other time I call the function. The first time I call it the variable userReviewCount stays at 0, the second time I call it it goes to 1, the third time it stays at 1, the fourth time it goes to 2 and so forth. I cannot get my head around why it is operating like this. To debug I outputed the res to the console, but the result is always "Result of update:[object Object]" Which gives me no information.

Does anyone have any ideas how I can debug this? I've thought of everything.

mcplums
  • 159
  • 2
  • 2
  • 9
  • Don't separate the find and update, there's a single method for that. There's also [`$inc`](https://docs.mongodb.com/manual/reference/operator/update/inc/) which increments atomically. Not to mention use [JSON.stringify](https://stackoverflow.com/a/4293047/2313887) to avoid the `[object Object]` thing. – Neil Lunn Nov 22 '18 at 02:43
  • Thanks I've updated to use the $inc! – mcplums Nov 22 '18 at 14:57

1 Answers1

0

You're having a problem with async code.

You are increasing current count after your database has responded, but you send the set query before you have incremented the response

Also, you dont need to query it twice, you can get the result from the findOne, change it and save

function saveUserReview(review) {
    var query = { 'filmId': review._filmId.toNumber() }

    collections.ReviewModel.findOne(query, function(err, result) {
        if (err) throw err;
        result.userReviewCount++;
        // could also be result.set(userReviewCount, result.userReviewCount + 1)
        result.save();

    });
}

I recommend reading about the async nature of javascript

Also, the reason you can't debug, is you are adding an object to a string so it transforms the object to a string [Object object] and prints it. The right way would be console.log("Result of update:", res); or make two different console.log

iagowp
  • 2,428
  • 1
  • 21
  • 32
  • Dude this is super helpful, thank you so much. Yes I have no understanding at all of the async nature of javascript. I will get learning! – mcplums Nov 22 '18 at 14:57