Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose findOneAndUpdate and upsert returns no errs, no documents affected

Tags:

I have a very minimal model:

var CompanySchema = new mongoose.Schema({     name: { type: String, required: true, unique: true }, });  var Company = mongoose.model('Company', CompanySchema) 

I am attempting to add a single document if it doesn't exist. Currently, there are no documents while I test:

models.Company.findOneAndUpdate({     name: 'companyName' }, {upsert: true}, function(err, numberAffected, raw){     console.log(err, numberAffected, raw) }) 

This is using the upsert options from the Mongoose docs

However err is null, numberAffected is null. Why isn't my document updated?

like image 420
mikemaccana Avatar asked Aug 04 '14 10:08

mikemaccana


People also ask

What does findOneAndUpdate return if not found?

The below example shows that the findOneAndUpdate method will return the null value if we have not found any matching document in the collection.

What does Mongoose findOneAndUpdate return?

By default, findOneAndUpdate() returns the document as it was before MongoDB applied update .

How do I update documents in findOneAndUpdate?

To make findOneAndUpdate() return the updated document, you need to use the returnDocument option. returnDocument has two possible values: 'before' and 'after' . The default behavior is 'before' , which means returning the document as it was before the update was applied. const testSchema = new mongoose.

What does Upsert mean mongoose?

May 20, 2019. In MongoDB, an upsert means an update that inserts a new document if no document matches the filter . To upsert a document in Mongoose, you should set the upsert option to the Model.


2 Answers

As of Mongoose 4+, do not forget to set new: true along with upsert or you will get the old document as a return value, not the updated one.

This is quite tricky especially when the request creates a document, as if you do not specify new: true, you receive a null document (there was no existing doc), but no error.

    var myObj = ...;     collection.findOneAndUpdate(     {uniqueAttr: myObj.uniqueAttr},     myObj,     {upsert: true, new: true},     function(...) {...} 
like image 88
Rayjax Avatar answered Sep 22 '22 15:09

Rayjax


in your code you are using the 3 parameter version of the method findOneAndUpdate so, according to the documentation you posted, the parameters are: A.findOneAndUpdate(conditions, update, callback).

You should use the 4th parameters version of the method to specify the upsert option.

I would like to point out that I never used the framework mongoose. Hope this helps.

Edit: Yes, in your case, conditions and update are the same. If your object is more complex then the one showed in the example, you might want to check for the _id or a "unique" (not guaranteed by MongoDB) attribute (better if it has an index on it). For example:

var myObj = ...; collection.findOneAndUpdate({uniqueAttr: myObj.uniqueAttr}, myObj, {upsert: true}, function(){      ... }); 
like image 22
Andrea Avatar answered Sep 22 '22 15:09

Andrea