Mongoose: findOneAndUpdate nie zwraca zaktualizowanego dokumentu

256

Poniżej znajduje się mój kod

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

Mam już trochę danych w bazie danych Mongo i chciałbym uruchomić ten kod, aby zaktualizować nazwę, dla której wiek to 17 lat, a następnie wydrukować wynik na końcu kodu.

Jednak dlaczego wciąż otrzymuję ten sam wynik z konsoli (nie zmodyfikowaną nazwę), ale kiedy idę do wiersza polecenia mongo db i wpisuję „ db.cats.find();”. Wynik przyszedł ze zmodyfikowaną nazwą.

Następnie wracam, aby ponownie uruchomić ten kod i wynik jest modyfikowany.

Moje pytanie brzmi: jeśli dane zostały zmodyfikowane, to dlaczego wciąż otrzymałem oryginalne dane przy pierwszym logowaniu na konsoli.log.

Marzenia
źródło

Odpowiedzi:

527

Dlaczego tak się dzieje?

Domyślny jest powrót do oryginalnego, niezmienionego dokumentu. Jeśli chcesz zwrócić nowy, zaktualizowany dokument, musisz przekazać dodatkowy argument: obiekt z newustawioną właściwością na true.

Z dokumentów mangusty :

Zapytanie # 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`
});

Dostępne opcje

  • new: bool - jeśli true , zwraca zmodyfikowany dokument zamiast oryginału. domyślnie ustawiony na false (zmieniony w 4.0)

Rozwiązanie

Podaj, {new: true}jeśli chcesz zaktualizowany wynik w doczmiennej:

//                                                         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);
});
XCS
źródło
15
Wydaje mi się, że jest to zepsute, nadal zwraca stary dokument z nowym: true.
PDN
@PDN Jaką masz wersję mongoose / mongo? To może być bałagan z tym, jak to działa.
Cole Erickson,
5
ma dla mnie sens, ponieważ masz już dostęp do nowego dokumentu
danday74,
3
zadziałało dla mnie, używam moogose w wersji 4.6.3, dzięki
cesar andavisa,
2
NodeJs MongoDB Native korzysta -{ returnOriginal: false }
Nick Grealy
78

Dla każdego, kto używa sterownika Node.js zamiast Mongoose, będziesz chciał użyć {returnOriginal:false}zamiast {new:true}.

Pedro Hoehl Carvalho
źródło
1
Dziękuję Ci! To działa dla mnie węzeł mongodb w wersji 2.2.27
Kevin Ng
6
To jest rodzaj idiotycznego API. Dlaczego nie użyć tych samych podpisów dla Mongoose jak natywnego API? Dlaczego nie zwrócić domyślnie zaktualizowanego dokumentu? Mongoose to jedna z bardziej irytujących lib, których używam na co dzień.
Askdesigners
56

Tak więc „findOneAndUpdate” wymaga opcji zwrotu oryginalnego dokumentu. Opcją jest:

Powłoka MongoDB

{returnNewDocument: true}

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

Mangusta

{new: true}

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

Interfejs API sterownika Node.js MongoDB:

{returnOriginal: false}

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

Tsuneo Yoshioka
źródło
Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta
39

Domyślnie findOneAndUpdate zwraca oryginalny dokument. Jeśli chcesz, aby zwrócił zmodyfikowany dokument, przekaż obiekt opcji { new: true }do funkcji:

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

});
hthserhs
źródło
2
dlaczego jest _idzerowy?
chovy
14

Dla każdego, kto natknął się na to przy użyciu stylu ES6 / ES7 z natywnymi obietnicami, oto wzór, który możesz przyjąć ...

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 */ }
Assaf Moldavsky
źródło
15
Mongoose zwróci obietnicę, jeśli nie zapewnisz funkcji oddzwaniania. Nie ma potrzeby tworzenia własnej obietnicy!
joeytwiddle
1
@joeytwiddle Mongoose nie zwróci obietnicy, jeśli nie oddzwonisz. Zamiast tego zwraca obiekt zapytania, który zapewnia tylko niewielki podzbiór interfejsu API Promise. Jest to zgodne z dokumentacją Mongoose.
Jamie Ridding,
13

To jest zaktualizowany kod dla findOneAndUpdate. To działa.

db.collection.findOneAndUpdate(    
  { age: 17 },      
  { $set: { name: "Naomi" } },      
  {
     returnNewDocument: true
  }    
)
Jobin Mathew
źródło
3

Jeśli chcesz zwrócić zmieniony dokument, musisz ustawić opcję {new:true}Odwołanie do interfejsu API, którego możesz użyćCat.findOneAndUpdate(conditions, update, options, callback) // executes

Podjęte przez oficjalny interfejs API Mongoose http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate można użyć następujących parametrów

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

Inną implementacją, która nie jest wyrażona na oficjalnej stronie interfejsu API i wolę korzystać z niej, jest Promiseimplementacja podstawowa, która pozwala mieć miejsce, w .catchktórym można poradzić sobie z wszystkimi różnymi błędami.

    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);
    });
Jonathan Thurft
źródło
2

Poniżej pokazano zapytanie dotyczące mangusty findOneAndUpdate. Tutaj new: truesłuży do pobrania zaktualizowanego dokumentu i fieldssłuży do uzyskania określonych pól.

na przykład. 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();
Sourabh Khurana
źródło
0

Wiem, że jestem już spóźniony, ale pozwólcie, że dodam tutaj moją prostą i działającą odpowiedź

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)
Aljohn Yamaro
źródło