Pourquoi ne pouvez-vous pas modifier les données renvoyées par une requête Mongoose (ex: findById)

94

Lorsque j'essaie de modifier une partie des données renvoyées par une requête Mongoose, cela n'a aucun effet.

J'essayais de comprendre cela pendant environ 2 heures hier, avec toutes sortes de _.clone()s, en utilisant des variables de stockage temporaires, etc. Enfin, juste au moment où je pensais devenir fou, j'ai trouvé une solution. J'ai donc pensé que quelqu'un dans le futur (fyuuuture!) Pourrait avoir le problème de sauvegarde.

Survey.findById(req.params.id, function(err, data){
    var len = data.survey_questions.length;
    var counter = 0;

    _.each(data.survey_questions, function(sq){
        Question.findById(sq.question, function(err, q){
            sq.question = q; //has no effect

            if(++counter == len) {
                res.send(data);
            }
        });
    });
});
Toli
la source
duplication possible de stackoverflow.com/q/9952649/4748042
martinho le

Réponses:

160

Pour des cas comme celui-ci où vous voulez un objet JS simple au lieu d'une instance de modèle complète, vous pouvez appeler lean()la chaîne de requête comme suit:

Survey.findById(req.params.id).lean().exec(function(err, data){
    var len = data.survey_questions.length;
    var counter = 0;

    _.each(data.survey_questions, function(sq){
        Question.findById(sq.question, function(err, q){
            sq.question = q;

            if(++counter == len) {
                res.send(data);
            }
        });
    });
});

Cette manière dataest déjà un objet JS simple que vous pouvez manipuler selon vos besoins.

JohnnyHK
la source
8
Btw @JohnnyHK voulait juste dire merci encore. Un an et demi plus tard, il aidait un client à déboguer quelque chose. Il a passé un week-end à essayer de comprendre quelque chose, il s'avère que c'était parce qu'il essayait de modifier l'objet Mongoose; P
Toli
1
2 ans plus tard et toujours en train de l'écraser. Je n'avais même pas réalisé que Lean () était là.
Petrogad
1
@Fizzix aggregatefournit toujours ses résultats sous forme d'objets simples, il n'est donc pas nécessaire d'utiliser lean().
JohnnyHK
1
3 ans plus tard et passé une heure entière à essayer de le comprendre. J'ai sauvé toute ma journée! Merci
Noy
2
Je vous remercie! Cela a vraiment aidé, mais pourquoi est-il impossible de modifier l'objet? De quel genre d'objet spécial s'agit-il?
Robert Fedus le
46

Je pense que la documentation Mongoose ne le clarifie pas assez, mais les données renvoyées dans la requête (bien que vous puissiez res.send () it) sont en fait un objet Mongoose Document, et PAS un objet JSON. Mais vous pouvez résoudre ce problème avec une seule ligne ...

Survey.findById(req.params.id, function(err, data){
    var len = data.survey_questions.length;
    var counter = 0;

    var data = data.toJSON(); //turns it into JSON YAY!

    _.each(data.survey_questions, function(sq){
        Question.findById(sq.question, function(err, q){
            sq.question = q;

            if(++counter == len) {
                res.send(data);
            }
        });
    });
});
Toli
la source
12
Vous pouvez également utiliser toObject(), qui fait la même chose que toJSON()mais avec un nom moins déroutant.
JohnnyHK
1
Est-ce que cela éliminera également les virtuels mis en place par le développeur?
mjwrazor le
5
TypeError: data.toObject is not a functionJ'ai eu ça, même avectoJSON
Luzan Baral
Au lieu de modifier le result, j'ai pu modifier result._doc.
nth-chile
@Luzan Baral C'est parce que vous utilisez ces fonctions pour l'objet Array. À utiliser à la JSON.parse(JSON.stringify(data))place pour les tableaux d'objets
mohit