How to update data inside an array - Mongoose

Viewed 40

I want to update this percentageOfReading variable inside that bookData array, can you guys help me?

This is mine database structure:

{
    "_id": {
        "$oid": "61181e4243613b2e643630cf"
    },
    "ownerId": "tKfJT-a6",
    "libraryId": "PRhs40DA",
    "libraryName": "Igor's Library",
    "__v": 0,
    "books": [{
        "bookData": {
            "bookId": "-DgQCwAAQBAJ",
            "percentageOfReading": 0
        }
    }]
}

So, I want to change the percentageOfReading value from 0 to any other number, and I was using this code, but anyways it was wrong:

        libraryModel.updateOne({'books.bookId': bookId}, {'$set': {
            'books.$.bookData.percentageOfReading': `${readingPercentage}`
        }}, function err() {
            console.log("Erro")
        });
2 Answers

The filter document should specify books.bookData.bookId, not books.bookId.

libraryModel.updateOne(
    {'books.bookData.bookId': bookId}, 
    {'$set': {'books.$.bookData.percentageOfReading': `${readingPercentage}`}}, 
    function(error) {
        console.error(error.message,error.stack)
    }
);

Vanilla solution

Be sure to remember that books is an array of objects, a is a nested sub object of libraryModel.

First find the library; traverse the books sub-collection for the book, access the property to update and then save using the emitted library paremeter.

Here is how I solved your problem with good old vanilla techniques.

libraryModel.findOne({ 'ownerId': 'tKfJT-a6' }).exec((err, library) => {
    if (err) {
        throw err
    }
    library.books.filter(book => book.bookData.bookId === '-DgQCwAAQBAJ')[0]
        .bookData.percentageOfReading = 95;
    library.save()
})

Recommendation

Simplify the schema by avoiding the nested objects on a sub-collection. This will speed up retrieval of data because and the code will be more concise.

const recommendedLibrary = new mongoose.Schema({
    ownerId: String,
    libraryId: String,
    libraryName: String,
    books: [{ 
        bookId: String, 
        percentageOfReading: Number 
    }]
})
  • Considering the above the update statement from the question will be valid.
Related