Как я могу создать/найти в 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()
не будет работать, потому что он попытается изменить существующий документ и получить "повторяющийся индекс ошибок ключа"
Ответы
Ответ 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);
};