¿Por qué no puede modificar los datos devueltos por Mongoose Query (por ejemplo, findById)?

94

Cuando intento cambiar cualquier parte de los datos devueltos por Mongoose Query, no tiene ningún efecto.

Estuve tratando de resolver esto durante aproximadamente 2 horas ayer, con todo tipo de _.clone()s, usando variables de almacenamiento temporal, etc. Finalmente, justo cuando pensé que me estaba volviendo loco, encontré una solución. Así que pensé que alguien en el futuro (¡fyuuuture!) Podría tener el problema de guardar.

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
fuente
posible duplicado de stackoverflow.com/q/9952649/4748042
martinho

Respuestas:

160

Para casos como este en los que desea un objeto JS simple en lugar de una instancia de modelo completa, puede llamar lean()a la cadena de consultas de la siguiente manera:

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

De esta forma dataya es un objeto JS simple que puede manipular según sea necesario.

JohnnyHK
fuente
8
Por cierto @JohnnyHK solo quería dar las gracias nuevamente. Un año y medio después estaba ayudando a un cliente a depurar algo. Pasó un fin de semana tratando de averiguar algo, resulta que fue porque estaba tratando de modificar el Objeto Mongoose; P
Toli
1
2 años después y todavía triturándolo. Ni siquiera me di cuenta de que lean () estaba allí.
Petrogad
1
@Fizzix aggregatesiempre proporciona sus resultados como objetos simples, por lo que no es necesario lean().
JohnnyHK
1
3 años después y pasé una hora entera tratando de resolverlo. ¡Salvó mi día entero! Gracias
Noy
2
¡Gracias! Esto realmente ayudó, pero ¿por qué es imposible modificar el objeto? ¿Qué tipo de objeto especial es?
Robert Fedus
46

Creo que la documentación de Mongoose no deja esto lo suficientemente claro, pero los datos devueltos en la consulta (aunque puede res.send ()) es en realidad un objeto Mongoose Document y NO un objeto JSON. Pero puedes arreglar esto con una línea ...

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
fuente
12
También puede usar toObject(), que hace lo mismo que toJSON()pero con un nombre menos confuso.
JohnnyHK
1
¿Esto también eliminará los virtuales puestos por el desarrollador?
mjwrazor
5
TypeError: data.toObject is not a functionTengo esto, lo mismo contoJSON
Luzan Baral
En lugar de modificar el result, pude modificar result._doc.
nth-chile
@Luzan Baral Eso es porque estás usando estas funciones para el objeto Array. Úselo en su JSON.parse(JSON.stringify(data))lugar para matrices de objetos
mohit