Подтвердить что ты не робот

Как я могу создать/найти в Mongoose?

Иногда мне нужен документ для существования в БД, и я рад либо работать с существующим документом, либо создавать документ, если он отсутствует, и работать с новым.

Это похоже на довольно распространенный случай использования, но я просмотрел Mongoose docs, и я ничего не могу найти.

Методы Mongoose Collection, такие как findOneAndUpdate() и update() с upsert: true, касаются изменения документов - я не хочу изменять документ, если он существует, просто получите ссылку на него.

Пример: (добавлено для @neillunn) Я хочу добавить пользователя со ссылкой на компанию, чье "имя" - "foo". До этого я хотел бы найти компанию с {name: 'foo'} и создать ее, если она не существует.

Пример 2: (добавлен для @neillunn) код, который я использую сейчас для обработки сценария примера:

// 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)
    })
}

Примечание: findOneAndUpdate() не будет работать, потому что он попытается изменить существующий документ и получить "повторяющийся индекс ошибок ключа"

4b9b3361

Ответ 1

Как указано в комментариях, есть плагин для mongoose, который делает это: http://github.com/drudge/mongoose-findorcreate

Этот поток также описывает способ достижения этого без плагина. Я просто не уверен, хотя, если он работает с мангустом.

Ответ 2

Очень полезное решение здесь: fooobar.com/info/185822/...:

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);
});

Еще более интересно, когда используется 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);
    };