Mongoose: findOneAndUpdate ne renvoie pas le document mis à jour

257

Ci-dessous mon code

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

J'ai déjà un enregistrement dans ma base de données mongo et je voudrais exécuter ce code pour mettre à jour le nom de l'âge de 17 ans, puis imprimer le résultat à la fin du code.

Cependant, pourquoi j'obtiens toujours le même résultat de la console (pas le nom modifié) mais quand je vais sur la ligne de commande mongo db et que je tape " db.cats.find();". Le résultat est venu avec un nom modifié.

Ensuite, je reviens pour exécuter à nouveau ce code et le résultat est modifié.

Ma question est: si les données ont été modifiées, alors pourquoi j'ai quand même obtenu les données d'origine lors de la première utilisation de console.log.

Rêves
la source

Réponses:

528

Pourquoi ça arrive?

La valeur par défaut est de renvoyer le document d' origine non modifié . Si vous souhaitez que le nouveau document mis à jour soit renvoyé, vous devez passer un argument supplémentaire: un objet avec la newpropriété définie sur true.

De la documentation mangouste :

Requête # 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`
});

Options disponibles

  • new: bool - si vrai , retourne le document modifié plutôt que l'original. par défaut à false (changé dans 4.0)

Solution

Passez {new: true}si vous voulez le résultat mis à jour dans la docvariable:

//                                                         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
la source
15
Cela semble être cassé pour moi, il renvoie toujours l'ancien document avec le nouveau: vrai.
PDN
@PDN Quelle version de mangouste / mongo possédez-vous? Cela pourrait jouer avec la façon dont cela fonctionne.
Cole Erickson
5
est logique pour moi puisque vous avez déjà accès au nouveau document
danday74
3
cela a fonctionné pour moi, j'utilise la version 4.6.3 de moogose, merci
cesar andavisa
2
NodeJs MongoDB Native utilise -{ returnOriginal: false }
Nick Grealy
78

Pour toute personne utilisant le pilote Node.js au lieu de Mongoose, vous voudrez utiliser à la {returnOriginal:false}place de {new:true}.

Pedro Hoehl Carvalho
la source
1
Je vous remercie! Cela fonctionne pour moi la version 2.2.27 du nœud mongodb
Kevin Ng
6
C'est en quelque sorte une API idiote. Pourquoi ne pas utiliser les mêmes signatures pour Mongoose que l'API native? Pourquoi ne pas retourner le document mis à jour par défaut? La mangouste est l'une des bibliothèques les plus irritantes que j'utilise tous les jours.
Askdesigners
56

Ainsi, "findOneAndUpdate" nécessite une option pour retourner le document d'origine. Et, l'option est:

Shell MongoDB

{returnNewDocument: true}

Réf: https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

Mangouste

{new: true}

Réf: http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

API du pilote Node.js MongoDB:

{returnOriginal: false}

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

Tsuneo Yoshioka
la source
Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta
39

Par défaut, findOneAndUpdate renvoie le document d'origine. Si vous souhaitez qu'il renvoie le document modifié, passez un objet options { new: true }à la fonction:

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

});
hthserhs
la source
2
pourquoi est _idnul?
chovy
14

Pour ceux qui sont tombés sur cela en utilisant le style ES6 / ES7 avec des promesses natives, voici un modèle que vous pouvez adopter ...

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
la source
15
Mongoose renverra une promesse si vous ne fournissez pas de fonction de rappel. Inutile de créer votre propre promesse!
joeytwiddle
1
@joeytwiddle Mongoose ne retournera pas de promesse si vous ne fournissez pas de rappel. Au lieu de cela, il renvoie un objet Query qui ne fournit qu'un petit sous-ensemble de l'API Promise. C'est selon la documentation Mongoose.
Jamie Ridding du
13

Il s'agit du code mis à jour pour findOneAndUpdate. Ça marche.

db.collection.findOneAndUpdate(    
  { age: 17 },      
  { $set: { name: "Naomi" } },      
  {
     returnNewDocument: true
  }    
)
Jobin Mathew
la source
9

Mainteneur de mangouste ici. Vous devez définir l' newoption sur true(ou, de manière équivalente, returnOriginalsur false)

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

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

Voir les documents MongoosefindOneAndUpdate() et ce tutoriel sur la mise à jour des documents dans Mongoose .

vkarpov15
la source
Je me suis trompé pour écrire returnNewDocument au lieu de juste nouveau. Merci pour l'aide!
user1111527
3

Si vous souhaitez renvoyer le document modifié, vous devez définir l'option de {new:true}référence API que vous pouvez utiliserCat.findOneAndUpdate(conditions, update, options, callback) // executes

Pris par l'API officielle Mongoose http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate, vous pouvez utiliser les paramètres suivants

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

Une autre implémentation qui n'est pas exprimée dans la page officielle de l'API et c'est ce que je préfère utiliser est l' Promiseimplémentation de base qui vous permet d'avoir .catchlà où vous pouvez traiter toutes vos diverses erreurs.

    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
la source
2

Ci-dessous montre la requête pour mangouste findOneAndUpdate. Ici new: trueest utilisé pour obtenir le document mis à jour et fieldsest utilisé pour obtenir des champs spécifiques.

par exemple. 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
la source
1

Je sais, je suis déjà en retard mais permettez-moi d'ajouter ma réponse simple et fonctionnelle ici

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
la source