Javascript 如何在猫鼬中创建/查找?

Javascript 如何在猫鼬中创建/查找?,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,有时我需要一个文档存在于数据库中,我很乐意使用现有的文档,或者创建缺少的文档,然后使用新文档 这似乎是一个相当常见的用例,但我已经查看了,但找不到任何东西 Mongoose收集方法,如findOneAndUpdate()和update()和upsert:true都是关于修改文档的-如果文档存在,我不想修改它,只要获取它的引用即可 示例:(为@neillunn添加)我想添加一个用户,该用户引用的公司的“名称”为“foo”。在此之前,我想查找一个名为{name:'foo'}的公司,如果它不存在,就创

有时我需要一个文档存在于数据库中,我很乐意使用现有的文档,或者创建缺少的文档,然后使用新文档

这似乎是一个相当常见的用例,但我已经查看了,但找不到任何东西

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()
将无法工作,因为它将尝试修改现有文档,并获取“重复键错误索引”

如评论中所述,mongoose有一个插件可以做到这一点:


还描述了一种无需插件即可实现此功能的方法。我只是不确定它是否适用于猫鼬。

非常有用的解决方案:

当习惯于承诺时更有趣:

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);
    };
可以找到,如果数据不存在,它将创建数据。基本上如下所示:

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,则文档将在更新前包含文档(或插入前为null)。如果为true,则文档包含更新或创建后的文档。虽然false是默认选项,但我想大多数人实际上更喜欢它为true


如果希望Mongoose运行验证程序,则必须设置
runValidators:true
选项。默认情况下,使用
findOneAndUpdate()

不太清楚时,不会执行这些命令。您看到的是正确的东西,但为什么您只想基本上“查找”它是否存在,以及“修改/升级”它是否存在?这种差异似乎不言自明。也许可以更好地解释您的用例。那么您基本上希望实现自动关系?由于mongoose没有官方或程序支持关系,我认为您需要执行两个查询来实现这一点。@Charminbear Not relations,只是根据需要查找或制作。如果我的示例是因为需要引用
公司而查找/创建公司实例。\u id
但这只是当前的用例。@Mikemacana:您正在搜索类似的内容?非常有用的解决方案:
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
        }
    }
);