Mongoose: findOneAndUpdate non restituisce il documento aggiornato


257

Di seguito è il mio codice

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

Ho già qualche record nel mio database di mongo e vorrei eseguire questo codice per aggiornare il nome per il quale l'età ha 17 anni e quindi stampare il risultato alla fine del codice.

Tuttavia, perché ottengo ancora lo stesso risultato dalla console (non il nome modificato) ma quando vado alla riga di comando di mongo db e digito " db.cats.find();". Il risultato è arrivato con un nome modificato.

Quindi torno indietro per eseguire nuovamente questo codice e il risultato viene modificato.

La mia domanda è: se i dati sono stati modificati, allora perché ho ancora i dati originali quando console.log.

Risposte:


527

Perché questo succede?

L' impostazione predefinita è di restituire il documento originale e inalterato . Se si desidera restituire il nuovo documento aggiornato, è necessario passare un argomento aggiuntivo: un oggetto con la newproprietà impostata su true.

Dai documenti della mangusta :

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

Opzioni disponibili

  • new: bool - se vero , restituisce il documento modificato anziché l'originale. il valore predefinito è false (modificato in 4.0)

Soluzione

Passa {new: true}se vuoi il risultato aggiornato nella docvariabile:

//                                                         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
Questo sembra essere rotto per me, restituisce ancora il vecchio documento con new: true.
PDN,

@PDN Quale versione di mongoose / mongo hai? Potrebbe essere un problema con il modo in cui funziona.
Cole Erickson,

5
ha senso per me dato che hai già accesso al nuovo documento
danday74

3
ha funzionato per me, sto usando Moogose versione 4.6.3, grazie
Cesare Andavisa,

2
NodeJs MongoDB Native utilizza -{ returnOriginal: false }
Nick Grealy,

78

Per chiunque utilizzi il driver Node.js anziché Mongoose, ti consigliamo di utilizzare {returnOriginal:false}invece di {new:true}.


1
Grazie! Questo funziona per me versione 2.2.27 del nodo mongodb
Kevin Ng,

6
Questo è un tipo di API idiota. Perché non utilizzare le stesse firme per Mongoose dell'API nativa? Perché non restituire il documento aggiornato per impostazione predefinita? Mongoose è una delle librerie più irritanti che uso ogni giorno.
Askdesigners

56

Pertanto, "findOneAndUpdate" richiede un'opzione per restituire il documento originale. E l'opzione è:

Shell MongoDB

{returnNewDocument: true}

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

Mangusta

{new: true}

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

API del driver MongoDB di Node.js:

{returnOriginal: false}

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


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

39

Per impostazione predefinita findOneAndUpdate restituisce il documento originale. Se si desidera che restituisca il documento modificato, passare un oggetto opzioni { new: true }alla funzione:

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

});

2
perché è _idnullo?
amorevole

14

Per chi si è imbattuto in questo usando lo stile ES6 / ES7 con promesse native, ecco uno schema che puoi adottare ...

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 restituirà una promessa se non si fornisce una funzione di richiamata. Non è necessario creare la tua promessa!
joeytwiddle,

1
@joeytwiddle Mongoose non restituirà una Promessa se non fornisci una richiamata. Restituisce invece un oggetto Query che fornisce solo un piccolo sottoinsieme dell'API Promise. Questo è secondo la documentazione di Mongoose.
Jamie Ridding,

13

Questo è il codice aggiornato per findOneAndUpdate. Funziona.

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


3

Se si desidera restituire il documento modificato, è necessario impostare l'opzione {new:true}API riferimento che è possibile utilizzareCat.findOneAndUpdate(conditions, update, options, callback) // executes

Preso dall'API Mongoose ufficiale http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate è possibile utilizzare i seguenti parametri

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

Un'altra implementazione che non è espressa nella pagina API ufficiale ed è ciò che preferisco usare è l' Promiseimplementazione di base che ti consente di avere .catchdove puoi gestire tutti i tuoi vari errori lì.

    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

Di seguito mostra la query per la mangusta findOneAndUpdate. Qui new: trueviene utilizzato per ottenere il documento aggiornato e fieldsviene utilizzato per ottenere campi specifici.

per esempio. 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();

1

Lo so, sono già in ritardo, ma vorrei aggiungere qui la mia risposta semplice e funzionante

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.