Por que você não pode modificar os dados retornados por uma Consulta Mongoose (ex: findById)


94

Quando tento alterar qualquer parte dos dados retornados por uma Consulta do Mongoose, isso não tem efeito.

Eu estava tentando descobrir isso por cerca de 2 horas ontem, com todos os tipos de programas _.clone(), usando variáveis ​​de armazenamento temporário, etc. Finalmente, quando pensei que estava ficando louco, encontrei uma solução. Portanto, imaginei que alguém no futuro (fyuuuture!) Pode ter o problema de salvar.

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


Respostas:


160

Para casos como este, em que você deseja um objeto JS simples em vez de uma instância de modelo completa, você pode chamar lean()a cadeia de consulta assim:

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

Dessa forma, datajá é um objeto JS simples que você pode manipular conforme necessário.


8
Btw @JohnnyHK só queria agradecer novamente. Um ano e meio depois, estava ajudando um cliente a depurar algo. Ele passou um fim de semana tentando descobrir algo, mas acabou descobrindo que era porque ele estava tentando modificar o Objeto Mongoose; P
Toli

1
2 anos depois e ainda esmagando. Nem percebi que lean () estava lá.
Petrogad

1
@Fizzix aggregatesempre fornece seus resultados como objetos simples, então não há necessidade de lean().
JohnnyHK

1
3 anos depois, passei uma hora inteira tentando descobrir. Salvei meu dia inteiro! Obrigado
Noy

2
Obrigado! Isso ajudou muito, mas por que é impossível modificar o objeto? Que tipo de objeto especial é?
Robert Fedus

46

Acho que a documentação do Mongoose não deixa isso claro o suficiente, mas os dados retornados na consulta (embora você possa res.send () isso) são, na verdade, um objeto de documento do Mongoose e NÃO um objeto JSON. Mas você pode consertar isso com uma linha ...

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

12
Você também pode usar toObject(), que faz a mesma coisa que, toJSON()mas com um nome menos confuso.
JohnnyHK

1
Isso também eliminará os virtuais colocados pelo desenvolvedor?
mjwrazor

5
TypeError: data.toObject is not a functionEu tenho isso, o mesmo comtoJSON
Luzan Baral

Em vez de modificar o result, fui capaz de modificar result._doc.
enésimo chile

@Luzan Baral Isso é porque você está usando essas funções para o objeto Array. Use em seu JSON.parse(JSON.stringify(data))lugar para Matrizes de objeto
mohit
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.