i have a product schema in my project, users can rate the products..the way i set the schema up is to store the number and sum of user ratings, then have a rating field where i would calculate the average of ratings so i can sort by it, but i can't find a way to automatically update this field whenever the product is updated.
the closest solution i had is to have the rating field's default value be a function that calculates the rating, but again it doesn't run automatically after the product's update
my schema looks like this
const productSchema = new Schema({
title: {
type: String,
required: true
},
views: {
type: Number,
default: 0
},
sumOfRatings: {
type: Number,
default: 0
},
numOfRatings: {
type: Number,
default: 0
},
rating: {
type: Number,
default: function() {
return this.sumOfRatings / this.numOfRatings
}
}, { collection: "Products", timestamps: true });
the question here describes something similar to what i want but there is no answer that does what i need
CodePudding user response:
You can define a middleware for the findAndUpdateOne
function, like this:
schema.pre('findOneAndUpdate', async function() {
const docToUpdate = await this.model.findOne(this.getQuery());
});
In this, you will first fetch the document and then set the updated value of the ratings.
CodePudding user response:
i had to do something like this in the end..find the place, get sum and num of ratings from it and then calculate rating and do another query to update it with it, then call the updating function whenever needed..not a big fan of this solution but that's what i could come up with
function updateProductRating(id) {
Product.findById(id).then(product=> {
let calcRating = product.sumOfRatings / product.numOfRatings;
Product.findByIdAndUpdate(id, { rating: calcRating }).then(result=>{
console.log("###### update rating ######")
console.log(result)
})
})
}