Mongoose: findOneAndUpdate не повертає оновлений документ


256

Нижче мій код

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 це.

Відповіді:


527

Чому це відбувається?

За замовчуванням - повернути оригінальний, незмінний документ. Якщо ви хочете повернути новий оновлений документ, ви повинні передати додатковий аргумент: об’єкт із 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)

Рішення

Передайте, {new: true}якщо потрібно оновлений результат у docзмінній:

//                                                         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);
});

15
Здається, це для мене порушено, він як і раніше повертає старий документ з новим: true.
PDN

@PDN Яка версія мангуста / монго у вас є? Це може заплутатися з тим, як це працює.
Коул Еріксон

5
має сенс для мене, оскільки ви вже маєте доступ до нового документа
понеділок74

3
це працювало для мене, я використовую moogose версії 4.6.3, спасибі
cesar andavisa

2
NodeJs MongoDB Native uses -{ returnOriginal: false }
Nick

78

Для всіх, хто використовує драйвер Node.js замість Mongoose, ви хочете використовувати {returnOriginal:false}замість {new:true}.


1
Дякую! Для мене це працює у версії mongodb версії 2.2.27
Кевін Нг

6
Це свого роду ідіотський API. Чому б не використати ті ж підписи для Mongoose, як і рідний API? Чому б не повернути оновлений документ за замовчуванням? Мангуст - одна з найбільш дратівливих вуст, якими я користуюся щодня.
Запитувальники

56

Отже, "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

API драйвера Node.js MongoDB:

{returnOriginal: false}

Посилання: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate


Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta

39

За замовчуванням findOneAndUpdate повертає оригінальний документ. Якщо ви хочете, щоб він повернув модифікований документ, передайте функцію об'єкта параметрів { new: true }:

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

});

2
чому _idнуль?
чови

14

Для тих, хто наткнувся на це, використовуючи стиль 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 */ }

15
Mongoose поверне обіцянку, якщо ви не надаєте функцію зворотного дзвінка. Немає необхідності створювати власну обіцянку!
joeytwiddle

1
@joeytwiddle Mongoose не поверне обіцянку, якщо ви не надасте зворотній дзвінок. Натомість він повертає об’єкт Query, який надає лише невеликий підмножина API Promise. Це згідно з документацією Мангуста.
Джеймі Ріддінг

13

Це оновлений код для findOneAndUpdate. Це працює.

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

8

Тут мангустський супровідник. Вам потрібно встановити newпараметр на true(або, що еквівалентно, returnOriginalна false)

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

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

Дивіться документи " Мангуста"findOneAndUpdate() та цей підручник щодо оновлення документів у "Мангуста" .


Я помилився записати returnNewDocument замість просто нового. дякую за допомогу!
user1111527

3

Якщо ви хочете повернути змінений документ, вам потрібно встановити параметр {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);
    });

2

Нижче показано запит на мангусти 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();

0

Я знаю, я вже спізнююсь, але дозвольте тут додати свою просту і працюючу відповідь

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.