简体   繁体   中英

Unsuccessfully updating Mongoose subdocument

I currently have a Mongoose schema for Item documents, which has a subdocument called linkedItems. The 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 linked items have a score attribute which stores the strength of the relationship between the parent Item document and each linkedItem . I have a function updateLinkedItemRating , which when passed a new rating, the parent item ID, and the linked item ID, is supposed to update the score of the linked item by averaging in the new score ( currentNumberOfRatings is the number of ratings that have thus far been averaged into the score). The following piece of code within updateLinkedItemRating is supposed to update this score, based on documentation I found on Mongoose subdocuments. It correctly calculates the new score, however the DB is not updated properly and both err and result in the callback are logging 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
        }
    );
});

You shouldn't need the findOneAndUpdate, as you already have the linkedItem when you do

const linkedItem = item.linkedItems.id(linkedItemId);

So you could just set those properties and then use .save()

linkedItem.score = newAverageScore;
linkedItem.currentNumberOfRatings = currentTotalNumberOfRatings;
item.save(function(err, result){
  console.log(err);
  console.log(result);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM