Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose embedded document updating

I have a problem with embedded document update.

My defined Schemas:

var Talk = new Schema({
    title: {
        type: String,
        required: true
    },
    content: {
        type: String,
        required: true
    },
    date: {
        type: Date,
        required: true
    },
    comments: {
        type: [Comments],
        required: false
    },
    vote: {
        type: [VoteOptions],
        required: false
    },
});

var VoteOptions = new Schema({
    option: {
        type: String,
        required: true
    },
    count: {
        type: Number,
        required: false
    }
});

Now I would like to update vote.count++, with given Talk id and VoteOption id. I have the following function to do the job:

function makeVote(req, res) {

    Talk.findOne(req.params.id, function(err, talk) {
        for (var i = 0; i < talk.vote.length; i++) {
            if (talk.vote[i]._id == req.body.vote) {
                talk.vote[i].count++;

            }
        }
        talk.save(function(err) {
            if (err) {
                req.flash('error', 'Error: ' + err);
                res.send('false');
            } else {
                res.send('true');
            }
        });
    });
}

Everything executes, I get back the res.send('true'), but the value on count does not change.

When I did some console.log I saw that it changed the value, but the talk.save just doesn't save it in db.

Also I'm quite unhappy about the cycle just to find _id of embedded doc. In the mongoose documentation I read about talk.vote.id(my_id) but that gives me error of not having an id function.

like image 767
rskuja Avatar asked Nov 03 '11 21:11

rskuja


Video Answer


1 Answers

When updating a Mixed type (which seems to be anything else than a basic type, so that also includes embedded documents), one has to call .markModified on the document. In this case, it would be:

talk.markModified("vote"); // mention that `talk.vote` has been modified

talk.save(function(err) {
    // ...
});

Hope this helps someone in the future since I couldn't find the answer very quickly.


Reference:

... Mongoose loses the ability to auto detect/save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

like image 143
pimvdb Avatar answered Oct 03 '22 03:10

pimvdb