Dlaczego nie możesz zmodyfikować danych zwróconych przez zapytanie Mongoose (np. FindById)

95

Kiedy próbuję zmienić jakąkolwiek część danych zwróconych przez zapytanie Mongoose, nie ma to żadnego efektu.

Próbowałem to rozgryźć wczoraj przez około 2 godziny, z różnymi rodzajami _.clone(), używając zmiennych tymczasowego przechowywania itp. W końcu, kiedy pomyślałem, że wariuję, znalazłem rozwiązanie. Więc pomyślałem, że ktoś w przyszłości (fyuuuture!) Może mieć problem z zapisywaniem.

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
źródło
1
możliwy duplikat Jak zmienić dokument Mongoose w zwykły obiekt?
Blakes Seven
możliwy duplikat stackoverflow.com/q/9952649/4748042
martinho

Odpowiedzi:

162

W takich przypadkach, w których chcesz zwykłego obiektu JS zamiast pełnej instancji modelu, możesz wywołać lean()łańcuch zapytań w następujący sposób:

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

W ten sposób datajest już zwykłym obiektem JS, którym możesz manipulować według potrzeb.

JohnnyHK
źródło
8
Btw @JohnnyHK chciał tylko jeszcze raz podziękować. Półtora roku później pomagałem klientowi coś debugować. Spędził weekend próbując coś wymyślić, okazuje się, że to dlatego, że próbował zmodyfikować obiekt Mongoose; P
Toli
1
2 lata później i nadal go miażdży. Nawet nie zdawałem sobie sprawy, że Lean () tam jest.
Petrogad
1
@Fizzix aggregatezawsze dostarcza wyniki jako zwykłe obiekty, więc nie ma takiej potrzeby lean().
JohnnyHK
1
3 lata później spędziłem całą godzinę próbując to rozgryźć. Uratowałem cały dzień! Dzięki
Noy
2
Dziękuję Ci! To naprawdę pomogło, ale dlaczego nie można zmodyfikować obiektu? Co to za specjalny przedmiot?
Robert Fedus
46

Myślę, że dokumentacja Mongoose nie wyjaśnia tego wystarczająco jasno, ale dane zwrócone w zapytaniu (chociaż można je res.send ()) są w rzeczywistości obiektem Mongoose Document, a NIE obiektem JSON. Ale możesz to naprawić jedną linią ...

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
źródło
12
Możesz także użyć toObject(), który robi to samo, toJSON()ale z mniej mylącą nazwą.
JohnnyHK
2
Czy to również pozwoli pozbyć się wirtuali założonych przez dewelopera?
mjwrazor
5
TypeError: data.toObject is not a functionMam to samo ztoJSON
Luzanem Baralem
Zamiast modyfikować result, mogłem zmodyfikować result._doc.
chile
@Luzan Baral To dlatego, że używasz tych funkcji dla obiektu Array. Użyj JSON.parse(JSON.stringify(data))zamiast tego dla Arrays of object
mohit