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();
" db.cats.find();
". Результат пришел с измененным именем.
Затем я снова запускаю этот код, и результат изменяется.
Мой вопрос: если данные были изменены, то почему я все еще получил оригинальные данные в первый раз, когда console.log их.
Ответы
Ответ 1
По умолчанию возвращается исходный, неизмененный документ. Если вы хотите, чтобы новый, обновленный документ был возвращен, вы должны передать дополнительный аргумент: объект с 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 - если true, вернуть измененный документ, а не оригинал. по умолчанию false (изменено в 4.0)
Итак, если вы хотите обновить результат в переменной doc
:
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}}, {new: true}, (err, doc) => {
if (err) {
console.log("Something wrong when updating data!");
}
console.log(doc);
});
Ответ 2
Для тех, кто использует драйвер Node.js вместо Mongoose, вы захотите использовать {returnOriginal:false}
вместо {new:true}
.
Ответ 3
Таким образом, "findOneAndUpdate" требует опции для возврата оригинального документа. И, вариант:
Оболочка MongoDB
{returnNewDocument: true}
Ссылка: https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/
Мангуста
{new: true}
Ссылка: http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate
Node.js API драйвера MongoDB:
{returnOriginal: false}
Ссылка: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate
Ответ 4
По умолчанию findOneAndUpdate возвращает исходный документ. Если вы хотите, чтобы он возвратил измененный документ, передайте объект параметров { new: true }
в функцию:
Cat.findOneAndUpdate({ age: 17 }, { $set: { name: "Naomi" } }, { new: true }, function(err, doc) {
});
Ответ 5
Для тех, кто наткнулся на это, используя стиль ES6/ES7 с родным promises, вот шаблон, который вы можете принять...
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 */ }
Ответ 6
Это обновленный код для findOneAndUpdate
. Он работает.
db.collection.findOneAndUpdate(
{ age: 17 },
{ $set: { name: "Naomi" } },
{
returnNewDocument: true
}
)
Ответ 7
Если вы хотите вернуть измененный документ, вам нужно установить опцию {new:true}
API-ссылку, которую вы можете использовать Cat.findOneAndUpdate(conditions, update, options, callback)//executes
Принято официальным API Mongoose 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);
});
Ответ 8
Ниже показан запрос для 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();
Ответ 9
Сопровождающий мангуст здесь. Вам нужно установить опцию new
на true
(или, что то же самое, от returnOriginal
до false
)
await User.findOneAndUpdate(filter, update, { new: true });
// Equivalent
await User.findOneAndUpdate(filter, update, { returnOriginal: false });
См. документы Mongoose findOneAndUpdate()
и это руководство по обновлению документов в Mongoose.