Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find one or create with Mongoose

I have

Page.findById(pageId).then(page => {   const pageId = page.id;    .. }); 

My problem is that if no page id is given, it should just take the first available page given some conditions, which is done by

Page.findOne({}).then(page => {   const pageId = page.id;   .. }); 

but if no page is found, it should create a new page and use this, which is done with

Page.create({}).then(page => {   const pageId = page.id;   .. }); 

But how do I combine all this to as few lines as possible?

I have a lot of logic going on inside

page => { ... } 

so I would very much like to do this smart, so I can avoid doing it like this

if (pageId) {   Page.findById(pageId).then(page => {     const pageId = page.id;      ..   }); } else {   Page.findOne({}).then(page => {     if (page) {       const pageId = page.id;       ..     } else {       Page.create({}).then(page => {         const pageId = page.id;         ..       });     }   }); } 

I am thinking I maybe could assign a static to the schema with something like

pageSchema.statics.findOneOrCreate = function (condition, doc, callback) {   const self = this;   self.findOne(condition).then(callback).catch((err, result) => {     self.create(doc).then(callback);   }); }; 
like image 418
Jamgreen Avatar asked Oct 18 '16 07:10

Jamgreen


People also ask

What is create in Mongoose?

Mongoose models have a create() function that is often used to create new documents. const User = mongoose.model('User', mongoose.Schema({ email: String })); const doc = await User.create({ email: '[email protected]' }); doc instanceof User; // true doc.email; // '[email protected]'

What does find do in Mongoose?

The find() function is used to find particular data from the MongoDB database. It takes 3 arguments and they are query (also known as a condition), query projection (used for mentioning which fields to include or exclude from the query), and the last argument is the general query options (like limit, skip, etc).

Does Mongoose model create collection?

Mongoose by default does not create any collection for the model in the database until any documents are created. The createCollection() method is used to create a collection explicitly.

Does Mongoose auto generate ID?

_id field is auto generated by Mongoose and gets attached to the Model, and at the time of saving/inserting the document into MongoDB, MongoDB will use that unique _id field which was generated by Mongoose.


2 Answers

As per the Mongoose docs:

As per previous SO answer

Model.findByIdAndUpdate()

"Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback."

In the options set upsert to true:

upsert: bool - creates the object if it doesn't exist. defaults to false.

Model.findByIdAndUpdate(id, { $set: { name: 'SOME_VALUE' }}, { upsert: true  }, callback) 
like image 55
Julian Boyce Avatar answered Oct 05 '22 13:10

Julian Boyce


Related to Yosvel Quintero's answer which didn't work for me:

pageSchema.statics.findOneOrCreate = function findOneOrCreate(condition, callback) {     const self = this     self.findOne(condition, (err, result) => {         return result ? callback(err, result) : self.create(condition, (err, result) => { return callback(err, result) })     }) } 

And then use it like:

Page.findOneOrCreate({ key: 'value' }, (err, page) => {     // ... code     console.log(page) }) 
like image 24
David Joos Avatar answered Oct 05 '22 14:10

David Joos