Почему вы не можете изменить данные, возвращаемые запросом Mongoose (например, findById)

95

Когда я пытаюсь изменить какую-либо часть данных, возвращаемых запросом Mongoose, это не дает никакого эффекта.

Вчера я пытался понять это около 2 часов, используя всевозможные _.clone()s, переменные временного хранения и т. Д. Наконец, когда я решил, что схожу с ума, я нашел решение. Итак, я подумал, что у кого-то в будущем (fyuuuture!) Может возникнуть проблема с сохранением.

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);
            }
        });
    });
});
Толи
источник
возможный дубликат stackoverflow.com/q/9952649/4748042
Мартиньо

Ответы:

161

В таких случаях, когда вам нужен простой объект JS вместо полного экземпляра модели, вы можете вызвать lean()цепочку запросов следующим образом:

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

Это dataуже простой объект JS, которым можно манипулировать по мере необходимости.

JohnnyHK
источник
8
Кстати, @JohnnyHK просто хотел еще раз поблагодарить. Через полтора года помогал клиенту что-то отладить. Он провел выходные, пытаясь что-то выяснить, оказалось, что это произошло из-за того, что он пытался модифицировать Объект Мангуст; P
Toli
1
2 года спустя и все еще сокрушает его. Даже не осознавал, что там был Lean ().
Петрогад
1
@Fizzix aggregateвсегда предоставляет свои результаты в виде простых объектов, поэтому в них нет необходимости lean().
JohnnyHK 01
1
3 года спустя, потратил целый час на то, чтобы понять это. Спас весь мой день! Спасибо
Ной
2
Спасибо! Это действительно помогло, но почему нельзя изменить объект? Что это за особенный объект?
Роберт Федус,
46

Я думаю, что в документации Mongoose это недостаточно ясно, но данные, возвращаемые в запросе (хотя вы можете res.send () it), на самом деле являются объектом Mongoose Document, а НЕ объектом JSON. Но вы можете исправить это одной строчкой ...

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
Вы также можете использовать toObject(), который делает то же самое, toJSON()но с менее запутанным именем.
JohnnyHK
1
Избавится ли это также от виртуальных машин, установленных разработчиком?
mjwrazor
5
TypeError: data.toObject is not a functionЯ получил это, то же самое сtoJSON
Лузан Барал
Вместо того result, чтобы изменять файл , я смог изменить result._doc.
nth-chile
@Luzan Baral Это потому, что вы используете эту функцию для объекта Array. Используйте JSON.parse(JSON.stringify(data))вместо этого для массивов объектов
mohit