53

I am using MongoDB with node js , i used npm install mongodb

I want to update an existing document and return the updated document , the document is updated correctly . but it returns the old document means the original document before update . i have used the returnNewDocument:true parameter but no use .

            var filter = {
                '_id': object_id
            },
            update = {
                $set: { "status" : data["status"] },
                $push: {
                    "statusHistory": {
                        $each: [{ status:data["status"],statusChangedTime:data["statusChangedTime"],comment:data["comment"]}],
                        $position:0,
                    }
                },
            }
            ,options = {
                //upsert: false,
                //multi: false,
                returnNewDocument: true
            };

            col.findOneAndUpdate(filter, update, options,function(err, res) {
                if (err) {

                    console.log(err);
                }else {

                    console.log(res);
                }
            });

the response is

{ lastErrorObject: { updatedExisting: true, n: 1 },
  value: 
   { 
//original document
   },     
  ok: 1 }

when i directly go to mongoDB through terminal and try

db.MyCollection.find().pretty();

the document is updated correctly, it just returns the original instead of updated one.

Stuck here for 2 hours, any help is appreciated

in package.json

"mongodb": "^2.1.4",
Zach Smith
  • 8,458
  • 13
  • 59
  • 133
Kanishka Panamaldeniya
  • 17,302
  • 31
  • 123
  • 193

9 Answers9

127

The Node.js driver documentation doesn't mention a returnNewDocument option for findOneAndUpdate() (which is an option for the MongoDB shell command with the same name).

Instead, it mentions an option called returnOriginal, which defaults to true. Try using that option, setting it to false to return the updated document instead of the original.

robertklep
  • 198,204
  • 35
  • 394
  • 381
18

To get the updated document after performing the update operation we need to use the option "returnDocument" : "after" along with "returnOriginal" : false.

As per the latest mongodb node driver v3.6 documentation, the usage of returnOriginal is deprecated. But when I try only including "returnDocument" : 'after' without "returnOriginal":false its returning the original record instead of the updated record. Using them both is giving the desired output of updated record instead of the original record. (source : http://mongodb.github.io/node-mongodb-native/3.6/api/Collection.html#findOneAndUpdate)

The option "returnNewDocument" : true is a mongo shell option and may not work in the node driver as per the official mongodb documentation ( mentioned here https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/)

13

If you are seeing this latest 2018, neither returnNewDocument:true nor returnOriginal: false, works. You have to instead set a property called new to true as in {.., new: true} in the option object for your query.

  • 1
    This is only true for `findAndModify`, which is deprecated: http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html#findAndModify . Instead use `findOneAndUpdate` http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html#findOneAndUpdate with `returnOriginal`. The naming inconsistencies are insane. – kevinmicke Aug 27 '19 at 15:06
8

=== Aug 2021

With the release of v4 of the node.js client, it seems the old solution of returnOriginal: false (which was awful anyway) is no longer the correct answer.

To see the list of available options for the node.js findOneAndUpdate method: https://mongodb.github.io/node-mongodb-native/4.0/interfaces/findoneandupdateoptions.html

But in short, this should work:

const doc = await <Collection>.findOneAndUpdate(
  { ... search },
  {
    $set: {
      field1: 'value 1',
      field2: ['value 2'],
      etc.
    },
  },
  {
    upsert: true,
    returnDocument: 'after', // this is new !
  }
)
Zach Smith
  • 8,458
  • 13
  • 59
  • 133
  • 1
    This is correct in case you have updated `mongodb` driver in Aug 2021. Gave me a real headache for 60 good minutes. Thanks @Zach! – Haywire Aug 15 '21 at 14:41
7

The NodeJS MongoDB driver has different arguments compared to the native MongoDB shell for the command findOneAndUpdate(). If you are using "mongodb": "^2.1.4" then use

returnOriginal: false

instead

returnNewDocument: true

.

Let's see below code:

db.collection('user_setting').findOneAndUpdate({user_id: data.user_id}, {$set: data}, {projection: dbConfig.userSetting, returnOriginal: false}, function (err, res) {
        if (err) {
            callback({'error': 1, 'message': 'Internal server error! ' + err, 'data': null, 'status': 500});
        }   else {
                 console.log(res);
                /* { lastErrorObject: { updatedExisting: true, n: 1 },
                      value: 
                           { user_id: 1,
                             notification_alert: 1,
                             notification_sound: 1,
                             user_setting_id: 2 
                            },
                       ok: 1 
                  }      */       
        }
    });
steampowered
  • 11,809
  • 12
  • 78
  • 98
yogesh kumar
  • 327
  • 1
  • 4
  • 15
4

If anyone else ran into this issue when using { returnOriginal: false } within a Mongoose setup:

Mongoose uses { new: true } instead of { returnOriginal: false }.

The feature is referenced here: Mongoose: findOneAndUpdate doesn't return updated document and within the Mongoose docs:

Options:

new: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)

So when using findOneAndUpdate add new: true to the method options:

...

const options = {
  new: true
};

col.findOneAndUpdate(filter, update, options, function (err, res) {
  if (err) {
    console.log(err);
  } else {
    console.log(res);
  }
});
jamesmhaley
  • 44,484
  • 11
  • 36
  • 49
3

According to the actual source code and type definition for 4.0+, the new property is now new. Set it true to return the modified result.

interface QueryFindOneAndUpdateOptions extends QueryFindOneAndRemoveOptions {
  /** if true, return the modified document rather than the original. defaults to false (changed in 4.0) */
  new?: boolean;
  ...
Ross Sheppard
  • 850
  • 1
  • 6
  • 14
1

I am using mongoose: 5.8.9

with these lines below

const option = { new: true }
const account = await Account.findOneAndUpdate(filter, update, option)

and this is working

Aljohn Yamaro
  • 2,629
  • 25
  • 22
0

This worked for me.

req.db.collection(collectionName).findOneAndUpdate(
          { _id : commentById._id }, // matching parameters
           updateOpts, //updating parameters
          {returnOriginal: false}  //don't use **returnNewDocument**
         );
Dharman
  • 30,962
  • 25
  • 85
  • 135
sareek
  • 534
  • 7
  • 12