Home » Nodejs » How can I create/find in Mongoose?

How can I create/find in Mongoose?

Posted by: admin November 30, 2017 Leave a comment

Questions:

Sometimes I need a document to exist in the DB, and am happy to either work with the existing document, or create the document if it’s missing, and work with the new one.

This seems like a fairly common use case, but I’ve looked through the Mongoose docs and I can’t find anything.

Mongoose Collection methods like findOneAndUpdate() and update() with upsert: true are about modifying documents – I don’t wish to modify the document if it exists, just get a reference to it.

Example: (added for @neillunn) I want to add a User with a reference to a Company whose ‘name’ is ‘foo’. Before that, I’d like to lookup a Company with {name: 'foo'} and create that if it doesn’t exist.

Example 2: (added for @neillunn) code I’m using now to handle the example scenario:

// Find or create an an instance and return a cb with a reference to it.
var findOrCreate = function(model, criteria, cb){
    model.update(criteria, criteria, {upsert: true}, function(err, numberAffected, raw){
        if ( ! raw.updatedExisting ) {
            console.log('Created instance')
        } else {
            console.log('Found existing instance')
        }           
        model.findOne(criteria, cb)
    })
}

Note: findOneAndUpdate() won’t work because it will try and modify the existing document, and get a ‘duplicate key error index’

Answers:

As stated in the comments, there is a plugin for mongoose that does this:
http://github.com/drudge/mongoose-findorcreate

This Thread also describes a way to achieve this without plugin. Im just not sure though if it works with mongoose.

Questions:
Answers:

Very useful solution here: https://stackoverflow.com/a/7592756/4025963:

var Counters = new Schema({
  _id: String,
  next: Number     
});

Counters.statics.findAndModify = function (query, sort, doc, options, callback) {
  return this.collection.findAndModify(query, sort, doc, options, callback);
};

var Counter = mongoose.model('counters', Counters);

Counter.findAndModify({ _id: 'messagetransaction' }, [], { $inc: { next: 1 } }, {}, function (err, counter) {
  if (err) throw err;
  console.log('updated, counter is ' + counter.next);
});

Even more interesting when used to promises:

Counters.statics.findAndModify =
    function findAndModify(query, sort, update, options, callback) {
        const promised = q.nbind(this.collection.findAndModify, this.collection);
        return promised(query || {}, sort || [], update || {}, options, callback);
    };