0

Here is my Schema,

var ProductSchema = new Schema({
_id: {
        type: Schema.Types.ObjectId,
        ref: "User"
    },
overall_rating: {
            average: {
                type: Number,
                default: null
            },
            rate_count:{
                type: Number,
                default: 0
            }
        }
});

What I need to do is to update "overall_rating.average" using only one mongoose query. ( cannot use two queries because of concurrency issues.)

If consider following terms

current_avg => current value in "overall_rating.average"
current_rate_count=> current value in "overall_rating.rate_count"
new_rating => new rating value

Query should be something like this

Product.findOneAndUpdate({ '_id': req.body.product_id }, { $set: { 'overall_rating.average': (current_avg*current_rate_count + new_rating)/(rate_count+1) }, {$inc: { overall_rating.rate_count: 1 }} }, { new: true }).exec(function(err, product) {
   if (err) {
       console.log(err);
       return res.json({ success: false, msg: err });
   } else {
       return res.json({ success: true, obj: product});
   }
});

It is a must to execute this as a one atomic query. So Cann't go with two steps (two queries)

Can anyone help me on this?

Achira Shamal
  • 527
  • 1
  • 5
  • 18
  • You cannot. You can `$inc` and you can `$mul` or anything else supported in the [field update operators](https://docs.mongodb.com/manual/reference/operator/update-field/) but there is no way to keep an "average". Bottom line is without keeping "both" a "count" and a "total", you cannot get an "average anyway". Just increment both a count and a total and divide them as you retrieve the results. – Neil Lunn May 28 '18 at 07:26
  • So you are telling that there is no variables which refers to current values during query execution ? – Achira Shamal May 28 '18 at 07:30
  • 1
    That's right, there's no such thing and never has been. You're essnetially asking the same thing others commonly ask, but just for a different purpose. Your best bet as stated is to instead use `$inc` to keep a "count" and a "total". You can obtain an "average" by reading those two properties from the document. – Neil Lunn May 28 '18 at 07:35

0 Answers0