Mongoose: findOneAndUpdate doesn't return updated document
Below is my code
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Cat = mongoose.model('Cat', {
name: String,
age: {type: Number, default: 20},
create: {type: Date, default: Date.now}
});
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}},function(err, doc){
if(err){
console.log("Something wrong when updating data!");
}
console.log(doc);
});
I already have some record in my mongo database and I would like to run this code to update name for which age is 17 and then print result out in the end of code.
However, why I still get same result from console(not the modified name) but when I go to mongo db command line and type "db.cats.find();
". The result came with modified name.
Then I go back to run this code again and the result is modified.
My question is: If the data was modified, then why I still got original data at first time when console.log it.
Solution 1:
Why this happens?
The default is to return the original, unaltered document. If you want the new, updated document to be returned you have to pass an additional argument: an object with the new
property set to true
.
From the mongoose docs:
Query#findOneAndUpdate
Model.findOneAndUpdate(conditions, update, options, (error, doc) => { // error: any errors that occurred // doc: the document before updates are applied if `new: false`, or after updates if `new = true` });
Available options
new
: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
Solution
Pass {new: true}
if you want the updated result in the doc
variable:
// V--- THIS WAS ADDED
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}}, {new: true}, (err, doc) => {
if (err) {
console.log("Something wrong when updating data!");
}
console.log(doc);
});
Solution 2:
For anyone using the Node.js driver instead of Mongoose, you'll want to use {returnOriginal:false}
instead of {new:true}
.
2021 - Mongodb ^4.2.0 Update{ returnDocument: 'after' }
Solution 3:
So, "findOneAndUpdate" requires an option to return original document. And, the option is:
MongoDB shell
{returnNewDocument: true}
Ref: https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/
Mongoose
{new: true}
Ref: http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate
Node.js MongoDB Driver API:
{returnOriginal: false}
2021 - Mongodb ^4.2.0 Update{ returnDocument: 'after' }
Ref: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate
Solution 4:
By default findOneAndUpdate returns the original document. If you want it to return the modified document pass an options object { new: true }
to the function:
Cat.findOneAndUpdate({ age: 17 }, { $set: { name: "Naomi" } }, { new: true }, function(err, doc) {
});
Solution 5:
For whoever stumbled across this using ES6 / ES7 style with native promises, here is a pattern you can adopt...
const user = { id: 1, name: "Fart Face 3rd"};
const userUpdate = { name: "Pizza Face" };
try {
user = await new Promise( ( resolve, reject ) => {
User.update( { _id: user.id }, userUpdate, { upsert: true, new: true }, ( error, obj ) => {
if( error ) {
console.error( JSON.stringify( error ) );
return reject( error );
}
resolve( obj );
});
})
} catch( error ) { /* set the world on fire */ }