如何在Mongoose中创建/查找?

时间:2014-08-04 11:05:23

标签: javascript node.js mongodb mongoose

有时我需要在DB中存在一个文档,并且很高兴能够使用现有文档,或者如果文档丢失则创建文档,并使用新文档。

这似乎是一个相当常见的用例,但我已查看了Mongoose docs,但我无法找到任何内容。

Mongoose收集方法,例如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()无法正常工作,因为它会尝试修改现有文档,并获得重复的密钥错误索引'

3 个答案:

答案 0 :(得分:11)

如评论中所述,有一个mongoose插件可以执行此操作: http://github.com/drudge/mongoose-findorcreate

This Thread还描述了一种在没有插件的情况下实现此目的的方法。我只是不确定它是否适用于猫鼬。

答案 1 :(得分:2)

Mongoose has an inbuilt findOneAndUpdate function可以找到,如果数据不存在,它将创建数据。基本上,下面是它的完成方式:

var modelDoc = new MyModel({ foo: 'bar' });

MyModel.findOneAndUpdate(
    {foo: 'bar'}, // find a document with that filter
    modelDoc, // document to insert when nothing was found
    {upsert: true, new: true, runValidators: true}, // options
    function (err, doc) { // callback
        if (err) {
            // handle error
        } else {
            // handle document
        }
    }
);

options参数对于使插入工作必不可少。`

通过设置upsert: true,如果{foo: 'bar'}过滤器未找到结果,则您命令MongoDB将modelDoc文档实际添加到集合中。

new: true选项更改了回调函数中返回的内容。如果为false,则doc将在更新之前包含该文档(或在插入之前为null)。如果为true,则doc将在更新或创建后包含文档。虽然false是默认选项,但我想大多数人实际上还是希望它为true。

如果您想让Mongoose运行验证程序,必须设置runValidators: true选项。默认情况下,使用findOneAndUpdate()时将不执行这些操作。

答案 2 :(得分:1)

非常有用的解决方案: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);
});

习惯承诺时更有趣:

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