I'm using mongoose in application and I have the following fields in my schema;
const CourseSchema = new mongoose.Schema({
...
feedback: {
count: {
type: Number,
default: 0,
},
ratings: {
clarity: {
type: Number,
default: 0,
},
engagement: {
type: Number,
default: 0,
},
completeness: {
type: Number,
default: 0,
}
}
}
})
Each time a user submits a feedback, the application performs an incremental average update using the current average and the count value. This means I would have to get the current numbers from the DB, update them with the new numbers and send them back. To do this, I use findById to get the document, get the existing numbers, update with the new values and update them in the DB using updateOne. Is there a way to do this all at once in one single query? I have seen some examples floating around, but they don't seem concrete enough for my use case.
Below is the code I am experimenting with right now. I'm pretty sure its not correct, but it should give an idea of what I'm trying to achieve.
await Course.findById(
id,
(error, course) => {
if (error) res.status(404).send("Course does not exist");
const { ratings } = req.body;
const { ratings: currRatings, count } = course.feedback;
Object.keys(currRatings).forEach(metric => {
/* Incremental averaging
newAverage = oldAverage + (newValue - oldAverage) / newSampleCount;
*/
(course.feedback.ratings[metric] =
course.feedback.ratings[metric] +
ratings[metric] - course.feedback.ratings[metric]) / (count +
1);
});
// increment the number of feedback by 1 for each feedback we receive
course.feedback.count += 1;
},
);