Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose instance .save() not working when embedded array object changed

I am using Mongoose npm module to manage mongodb. This is schema of mongodb collection what I am going to update.

var UserSchema = new Schema({
    username: {
        type: String,
        unique: true,
        required: true
    },
    email: {
        type: String,
        unique: true,
        required: true
    },
    cards: []
});
module.exports = mongoose.model('User', UserSchema);

inside post request, here req is request object of post request. and res is response object.

User.findById(userID).exec(function (err, doc) {
        let cardInfo = req.cardInfo
        let cardIndex = req.cardIndex
        doc["cards"][0] = cardInfo;
        console.log(doc)
/*  here I got right doc object as I requested
{
        "_id": "59f3bdd488f912234fcf06ab",
        "email": "[email protected]",
        "username": "test",
        "__v": 2,
        "cards": [
            {
                "testNo": "42424242424242"
            }
        ]
    }
*/
        doc.save(function (err) {
          if (err) {
            return res.json({
              success: false,
              msg: 'Card add error'
            });
          }
          res.json({
            success: true,
            msg: 'Successful updated card.'
          });
        });
})

I got message 'Successful updated card.', but actually, It doesn't save. How to solve it. Thanks.

like image 233
Nomura Nori Avatar asked Nov 05 '17 15:11

Nomura Nori


People also ask

What does save () do in mongoose?

Mongoose | save() Function The save() function is used to save the document to the database. Using this function, new documents can be added to the database.

Does Mongoose save overwrite?

Mongoose save with an existing document will not override the same object reference. Bookmark this question.

Does update call save in mongoose?

When you create an instance of a Mongoose model using new , calling save() makes Mongoose insert a new document. If you load an existing document from the database and modify it, save() updates the existing document instead.

How do I get the Objectid after I save an object in mongoose?

To get the object ID after an object is saved in Mongoose, we can get the value from the callback that's run after we call save . const { Schema } = require('mongoose') mongoose. connect('mongodb://localhost/lol', (err) => { if (err) { console. log(err) } }); const ChatSchema = new Schema({ name: String }); mongoose.


1 Answers

The problem is that mongoose don't knwo your array is modified.

You can use 2 solutions :

markModified

This function will mark the embedded element as modified and force a resave of it. It will tell mongoose to resave this element.

User.findById(userID).exec(function (err, doc) {
        let cardInfo = req.cardInfo
        let cardIndex = req.cardIndex
        doc["cards"][0] = cardInfo;
        console.log(doc)
/*  here I got right doc object as I requested
{
        "_id": "59f3bdd488f912234fcf06ab",
        "email": "[email protected]",
        "username": "test",
        "__v": 2,
        "cards": [
            {
                "testNo": "42424242424242"
            }
        ]
    }
*/
        doc.markModified('cards');
        doc.save(function (err) {
          if (err) {
            return res.json({
              success: false,
              msg: 'Card add error'
            });
          }
          res.json({
            success: true,
            msg: 'Successful updated card.'
          });
        });
})

Use a full schema.

To avoid the markModified trick, you should describe the content of cards in your schema. This way mongoose will be able to determine if it needs to save the field or not.

Here is the way to declare your schema properly :

const CardSchema = new Schema({
  testNo: String,
});

var UserSchema = new Schema({
    username: {
        type: String,
        unique: true,
        required: true
    },
    email: {
        type: String,
        unique: true,
        required: true
    },
    cards: [CardSchema]
});
module.exports = mongoose.model('User', UserSchema);

This way, mongoose will be able to detect if a value inside cards changed and save only the modified item.

If you can do it (static schema), this is clearly the good way to do it.

like image 181
Julien TASSIN Avatar answered Oct 04 '22 17:10

Julien TASSIN