MongoDB/Mongoose:使用 findOneAndUpdate() 更新整个文档

Com*_*gle 8 javascript mongoose mongodb

我想使用该findOneAndUpdate()方法来创建一个不存在的文档,或者如果存在则更新它。考虑以下代码:

SampleComment = new Comment({
    id: '00000001',
    name: 'My Sample Comment',
    ...
})
Run Code Online (Sandbox Code Playgroud)

这是我试图找出是否SampleComment已经存在,如果存在,更新它,否则创建它:

Comment.findOneAndUpdate(
    { id: SampleComment.id }, 
    { SampleComment }, // <- NOT PASSING THE OBJECT
    { upsert: true, setDefaultsOnInsert: true }, 
    function(error, result) {
        ...
});
Run Code Online (Sandbox Code Playgroud)

我试图将模型实例作为第二个参数中的对象传递,但结果仅返回模型的默认值。文档本身也是如此。

如何SampleComment在第二个参数中正确传递整个对象?

Sea*_*ean 5

当你调用什么实际发生的findOneAndUpdate()与你的Document对象作为您的更新对象与{ SampleComment }为你解构那是SampleComment : {...}

Mongoose 然后会去查看你的数据库文档中是否有任何名为 的属性SampleComment,没有找到,然后什么都不做。返回给您一个不会发生任何变化的文档。

您可以做些什么来解决这个问题,首先使用 Mongoose 的toObject()方法将您的 Document 转换回普通的更新对象,删除_id(因为该属性是不可变的,而且您无论如何都不想用更新替换它),然后将它与您的现有的findOneAndUpdate()方法。例如:

let newComment = SampleComment.toObject();
delete newComment._id;

Comment.findOneAndUpdate(
    { id: SampleComment.id }, 
    newComment,
    { upsert: true, setDefaultsOnInsert: true }, 
    function(error, result) {
        ...
    }
);

Run Code Online (Sandbox Code Playgroud)

然后,您可以在数据库中看到更新的文档。要接收更新的文档,您result还需要将选项传递{ new: true }给您的选项对象。

这是 Mongoose 的toObject()文档方法文档的链接。


Kai*_*rat 1

默认情况下,返回的结果将是未更改的文档。如果您希望返回新的、更新的文档,则必须传递一个new以值命名的附加参数true

Comment.findOneAndUpdate({id: SampleComment.id}, SampleComment, {new: true, upsert: true, setDefaultsOnInsert: true}, function(error, result) {
    if(error){
        console.log("Something wrong when updating data!");
    }

    console.log(result);
});
Run Code Online (Sandbox Code Playgroud)

请参阅http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

function(error, doc) {
  // error: any errors that occurred
  // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
}
Run Code Online (Sandbox Code Playgroud)