Mongoose subdocument update failed
I currently have a Mongoose schema for documents Item
that has a sub-document called linkedItems. These two are defined as follows:
const ItemSchema = new Schema({
description: { type: [String], required: true },
linkedItems: [linkedItemSchema],
});
const linkedItemSchema = new Schema({
_id: Schema.Types.ObjectId,
title: String,
score: Number,
currentNumberOfRatings: Number,
});
All related elements have an attribute score
that preserves the relationship between the parent document Item
and each linkedItem
. I have a function updateLinkedItemRating
that when passing in a new rating, parent ID and related item ID, it should update the rating of the related item by averaging over the new rating ( currentNumberOfRatings
this is the number of ratings that have been averaged in the score so far). The following code snippet inside updateLinkedItemRating
should update this score based on the documentation I found in the Mongoose sub-pages. He correctly calculates the new point, but the database is not updated properly, and both err
and result
callback registered as null. Any suggestions would be appreciated.
Item.findOne({ _id: parentItemId }, function(err, item) {
// Calculate new average score, this all works fine
const linkedItem = item.linkedItems.id(linkedItemId);
const currentTotalNumberOfRatings = linkedItem.currentNumberOfRatings;
const currentScore = linkedItem.score;
const newAverageNumerator = parseInt(currentScore) * parseInt(currentTotalNumberOfRatings) + parseInt(rating);
const newAverageDenominator = parseInt(currentTotalNumberOfRatings) + 1;
const newAverageScore = newAverageNumerator * 1.0 / newAverageDenominator;
console.log(newAverageScore); // This logs the proper number
//This does not update the DB as expected
Item.findOneAndUpdate(
{ _id: item._id, 'linkedItems._id': linkedItemId },
{
$set: {
'linkedItems.$.score': newAverageScore,
'linkedItems.$.currentNumberOfRatings': currentTotalNumberOfRatings + 1,
},
},
function (err, result) {
console.log(err); // Logs null
console.log(result); // Logs null
}
);
});
source to share
You don't need findOneAndUpdate as you already have an associated element when you do
const linkedItem = item.linkedItems.id(linkedItemId);
So you can just set these properties and then use .save ()
linkedItem.score = newAverageScore;
linkedItem.currentNumberOfRatings = currentTotalNumberOfRatings;
item.save(function(err, result){
console.log(err);
console.log(result);
});
source to share