Mongoose findOneAndUpdate 和 upsert 没有返回错误,也没有影响到任何文档。

27

我有一个非常简单的模型:

var CompanySchema = new mongoose.Schema({
    name: { type: String, required: true, unique: true },
});

var Company = mongoose.model('Company', CompanySchema)

我正在尝试添加一个文档,如果它不存在的话。当前在我的测试中没有任何文档:

models.Company.findOneAndUpdate({
    name: 'companyName'
}, {upsert: true}, function(err, numberAffected, raw){
    console.log(err, numberAffected, raw)
})

这里使用了 Mongoose 文档中的 upsert 选项

然而,errnullnumberAffected 也是 null。为什么我的文档没有更新?

2个回答

37

从Mongoose 4+开始,在使用upsert时不要忘记设置new: true,否则将返回旧文档而不是更新后的文档。

这一点非常棘手,特别是在请求创建文档时,如果没有指定new: true,您将收到一个空文档(因为没有现有文档),但不会报错。

    var myObj = ...;
    collection.findOneAndUpdate(
    {uniqueAttr: myObj.uniqueAttr},
    myObj,
    {upsert: true, new: true},
    function(...) {...}

3
谢谢夸奖!在升级到最新版本的Mongoose后,我一直很苦恼,但是你让我解脱了! - Vignesh T.V.

28

在您的代码中,您正在使用findOneAndUpdate方法的3个参数版本,因此根据您发布的文档,参数为:A.findOneAndUpdate(conditions, update, callback)

您应该使用第四个参数版本的方法来指定upsert选项。

我想指出我从未使用过mongoose框架。希望这可以帮助到您。

编辑: 是的,在您的情况下,条件更新是相同的。如果您的对象比示例中显示的更复杂,则可能要检查_id或“唯一”(MongoDB不能保证)属性(最好对其进行索引)。例如:

var myObj = ...;
collection.findOneAndUpdate({uniqueAttr: myObj.uniqueAttr}, myObj, {upsert: true}, function(){
     ...
});

5
有点奇怪:如果文档不存在,我希望只是创建一个文档,所以"conditions"和"update"是一样的,但这确实可以解决问题。 - mikemaccana
如果您想创建一个对象,请使用插入或创建。更新是用于查找已经存在的对象,然后更改其值。 - Nick Sotiros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接