Home > Net >  how to sort by an auto-calculated field in mongoose.js
how to sort by an auto-calculated field in mongoose.js

Time:08-24

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)
        })
    })
}
  • Related