Mongoose to define update-upsert does insert or update
I want to test if the "upsert" option for the update is woking fine. This way I "increment" the object twice in mongodb with the same key. However, it did not show the inserted message. Am I missing something?
(mongodb: v2.6.3; mongoose: 3.8.15)
Member.findOneAndRemove({user_id : 1},
function (err, doc) {
if (!err) onsole.log(doc ? 'deleted' : 'not found');
}); // -> deleted, make sure user_id = 1 doesn't exist
Member.update({user_id : 1},
{$set : {name:"name1"}},
{upsert : true, new : false}, // new : false, so that I can detect original doc is null then know it a new one.
function (err, doc) {
if (!err) {
console.log(doc ? 'updated' : 'inserted')
}
}); // -> updated ? But it shoule be inserted, right ?
Member.update({user_id : 1},
{$set : {name:"name2"}},
{upsert : true, new : false},
function (err, doc) {
if (!err) {
console.log(doc ? 'updated' : 'inserted')
}
}); // -> updated, yes, no problem.
Thanks for any hint.
============ Answer =============
Use . findOneAndUpdate instead of .update! Also, make sure the option is: {upsert: true, new: false } so that the second parameter (doc) of the callback can be the original document in the case.
source to share
Method .update()
in mongoose takes three argument to the callback: err
, numAffected
and a raw
response. Use the "raw" object to find out what happened:
Member.update({user_id : 1},
{$set : {name:"name1"}},
{upsert : true },
function (err, numAffected, raw) {
if (!err) {
console.log(raw)
}
});
You will see a structure like this:
{ ok: true,
n: 1,
updatedExisting: false,
upserted: [ { index: 0, _id: 5456fc7738209001a6b5e1be } ] }
Therefore, the values n
and "updatedExisting keys available, where the second is false on upserts and true otherwise.
upserted will contain the
_id" of any new documents are always created .
As far as n
or "numAffected" is concerned, it is basically always 1 where the document is matched against legacy-related responses.
You can see the new WriteResult response in MongoDB 2.6 and up using the Bulk Operations form:
var bulk = Member.collection.initializeOrderedBulkOp();
bulk.find({user_id : 1}.upsert().update({$set : {name:"name1"}});
bulk.execute(err,result) {
console.log( JSON.stringify( result, undefined, 2 ) );
}
On the first iteration, you will get something like this:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 1,
"nMatched": 0,
"nModified": 0,
"nRemoved": 0,
"upserted": [
{
"index": 0,
"_id": "5456fff138209001a6b5e1c0"
}
]
}
And the second one with the same parameters like this:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 1,
"nModified": 0,
"nRemoved": 0,
"upserted": []
}
And the document will be marked as "modified" where something was actually changed.
So anyway, the operations .update()
don't return the modified document or the original document. This is a method .findOneAndUpdate()
, a mongoose wrapper around the main one .findAndModify()
, that performs an atomic operation. Methods .update()
are generally for bulk operations and, as such, do not return document content.
source to share