Mongoose: findOneAndUpdate不返回更新后的文档

下面是我的代码

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');


var Cat = mongoose.model('Cat', {
name: String,
age: {type: Number, default: 20},
create: {type: Date, default: Date.now}
});


Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}},function(err, doc){
if(err){
console.log("Something wrong when updating data!");
}


console.log(doc);
});

我已经在我的mongo数据库中有一些记录,我想运行这段代码来更新年龄为17岁的名称,然后在代码的末尾打印结果。

然而,为什么我仍然从控制台得到相同的结果(不是修改后的名称),但当我进入mongo db命令行并键入“db.cats.find();”时。结果是修改后的名称。

然后我返回去再次运行这段代码,结果被修改了。

我的问题是:如果数据被修改了,那么为什么我仍然在console.log它的第一时间得到原始数据。

415152 次浏览

为什么会发生这种情况?

默认的返回原始的,不变的文档。如果你想要返回更新后的新文档,你必须传递一个额外的参数:一个new属性设置为true的对象。

猫鼬文档:

查询# findOneAndUpdate

Model.findOneAndUpdate(conditions, update, options, (error, doc) => {
// error: any errors that occurred
// doc: the document before updates are applied if `new: false`, or after updates if `new = true`
});

可用选项

  • new: bool——如果真正的,则返回修改文档而不是原始文档。默认为false(在4.0中更改)

解决方案

如果你想在doc变量中得到更新的结果,则传递{new: true}:

//                                                         V--- THIS WAS ADDED
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}}, {new: true}, (err, doc) => {
if (err) {
console.log("Something wrong when updating data!");
}


console.log(doc);
});

默认情况下,findOneAndUpdate返回原始文档。如果你想让它返回修改后的文档,将选项对象{ new: true }传递给函数:

Cat.findOneAndUpdate({ age: 17 }, { $set: { name: "Naomi" } }, { new: true }, function(err, doc) {


});

对于那些使用ES6 / ES7风格和本地承诺的人来说,这里有一个模式你可以采用…

const user = { id: 1, name: "Fart Face 3rd"};
const userUpdate = { name: "Pizza Face" };


try {
user = await new Promise( ( resolve, reject ) => {
User.update( { _id: user.id }, userUpdate, { upsert: true, new: true }, ( error, obj ) => {
if( error ) {
console.error( JSON.stringify( error ) );
return reject( error );
}


resolve( obj );
});
})
} catch( error ) { /* set the world on fire */ }

对于任何使用Node.js驱动而不是Mongoose的人来说,你会想要使用{returnOriginal:false}而不是{new:true}

< p > 2021年- Mongodb ^4.2.0更新
{ returnDocument: 'after' } < / p >

这是findOneAndUpdate的更新代码。它的工作原理。

db.collection.findOneAndUpdate(
{ age: 17 },
{ $set: { name: "Naomi" } },
{
returnNewDocument: true
}
)

所以,“findOneAndUpdate"需要返回原始文档的选项。选项是:

MongoDB shell

{returnNewDocument: true}

裁判:https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

猫鼬

{new: true}

裁判:http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

MongoDB Driver API:

{returnOriginal: false}

< p > 2021年- Mongodb ^4.2.0更新
{ returnDocument: 'after' } < / p >

裁判:http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate

如果你想返回修改后的文档,你需要设置选项{new:true} API引用,你可以使用Cat.findOneAndUpdate(conditions, update, options, callback) // executes

通过官方的Mongoose API http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate,你可以使用以下参数

A.findOneAndUpdate(conditions, update, options, callback) // executes
A.findOneAndUpdate(conditions, update, options)  // returns Query
A.findOneAndUpdate(conditions, update, callback) // executes
A.findOneAndUpdate(conditions, update)           // returns Query
A.findOneAndUpdate()                             // returns Query

另一个没有在官方API页面中表示的实现是Promise基本实现,它允许你有.catch,在那里你可以处理所有的各种错误。

    let cat: catInterface = {
name: "Naomi"
};


Cat.findOneAndUpdate({age:17}, cat,{new: true}).then((data) =>{
if(data === null){
throw new Error('Cat Not Found');
}
res.json({ message: 'Cat updated!' })
console.log("New cat data", data);
}).catch( (error) => {
/*
Deal with all your errors here with your preferred error handle middleware / method
*/
res.status(500).json({ message: 'Some Error!' })
console.log(error);
});

下面是对mongoose的findOneAndUpdate的查询。这里new: true用于获取更新后的文档,而fields用于获取特定的字段。

如。findOneAndUpdate(conditions, update, options, callback)

await User.findOneAndUpdate({
"_id": data.id,
}, { $set: { name: "Amar", designation: "Software Developer" } }, {
new: true,
fields: {
'name': 1,
'designation': 1
}
}).exec();

我是猫鼬的维护者。你需要将new选项设置为true(或等价地,将returnOriginal设置为false)。

await User.findOneAndUpdate(filter, update, { new: true });


// Equivalent
await User.findOneAndUpdate(filter, update, { returnOriginal: false });

参见Mongoose findOneAndUpdate()文档本教程介绍如何在Mongoose中更新文档

我知道,我已经迟到了,但让我在这里添加我的简单好用答案

const query = {} //your query here
const update = {} //your update in json here
const option = {new: true} //will return updated document


const user = await User.findOneAndUpdate(query , update, option)

在某些情况下{new: true}不起作用。 那么你可以试试这个。

{'returnNewDocument':true}

2021年- Mongodb ^4.2.0更新

这适用于mongodb节点驱动程序 mongoose。

似乎最新版本的Mongodb节点驱动程序使用了以下语法,如果你正在使用"collection.findOneAndUpdate"进行搜索和更新:

.findOneAndUpdate(query, update, { returnDocument: 'after' | 'before' })

我自己在搜索的时候找不到答案,所以把这个贴出来以防别人也有同样的情况。

export function newDocumentOnUpdatePlugin(schema) {
schema.pre(
['update', 'findOneAndUpdate', 'updateOne', 'updateMany'],
function (next) {
this.setOptions({ new: true });
next();
},
);
}

我已经创建了这个插件,如果有人需要整个应用程序的这个功能,想要避免重复。只需将其用作全球插件

此选项对于获取更新的文档实例是必需的

{ new: true }