Mongoose Populate возвращает пустой массив

Я получаю пустой массив со следующим кодом:

var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'mytestapp');

var SurveySchema = require('../models/Survey.js').SurveySchema;
var Survey = mongoose.model('SurveySchema', SurveySchema, 'surveys');


var UserSchema = require('../models/Survey.js').User;
var User = mongoose.model('user', UserSchema, 'users');

exports.getSurveysForUser = function(User) {
    return function (req, res) {


 User
        .findOne({_id: req.params.userId})
        .populate('surveys')
        .exec(function (err, user){
            if (err) return res.json({error: err})
            else {
                var surveyList=[];
                surveyList = user.surveys;
                console.log(surveyList);
                console.log("user: "+ user);
                res.json(surveyList);

            }
        });
}};

Это вывод консоли:

 [ ]

user: { __v: 2,
  _id: 52939b8c22a7efb720000003,
  email: '[email protected]',
  password: '202cb962ac59075b964b07152d234b70',
  surveys: []
}

Это модели Mongoose:

exports.SurveySchema = new Mongoose.Schema({
description : String,
questions : [question] });

exports.User = new Mongoose.Schema({
name : String,
email: { type: String, unique: true },
password: { type: String, required: true},
surveys :  [{type: Schema.ObjectId, ref: 'SurveySchema'}] });

Кстати:

Я уже пробовал User.findOne(...), а затем Survey.find() в обратном вызове. Казалось, что второе утверждение даже не было выполнено. По-видимому, я очень новичок в мангусте ... и я не могу найти способ обойти эту проблему.

У вас есть идеи, как мне помочь? Я не мог найти здесь никакого полезного решения, но проблема не должна быть большой. Заранее спасибо, это действительно не дает мне спать уже несколько дней!!

Изменить: Итак, это index.js с методом:

var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'mytestapp');

var SurveySchema = require('../models/Survey.js').SurveySchema;
var Survey = mongoose.model('SurveySchema', SurveySchema, 'surveys');



var UserSchema = require('../models/Survey.js').User;
var User = mongoose.model('user', UserSchema, 'users');

//.. here are some more methods.. 

exports.getSurveysForUser = function(User) {
return function (req, res) {
 User
            .findOne({_id: req.params.userId})
            .populate('surveys')
            .exec(function (err, user){
                if (err) return res.json({error: err})
                else {
                    var surveyList=[];
                    surveyList = user.surveys;
                    console.log(surveyList);
                    console.log("user: "+ user);
                    res.json(surveyList);

                }
            });
}};

//this is the code, that saves a response to a survey

exports.addResponse = function(ResponseSet) {
    return function (req, res) {
        console.log("bin da: addResponse");
        console.log("response zu: " + req.body.surveyId);
        console.log("von user : " + req.body.userId);

        //für user speichern

        var pUser = User.findOne({_id:req.body.userId}, function (error, user) {

                // Maybe populate doesnt work, because i only push the ID?

               user.surveys.push(Mongoose.Types.ObjectId(req.body.surveyId));

               user.save();

            }
        );



        var pSurvey = Survey.findOne({_id:req.body.surveyId}, function (error, survey) {
                survey.responses.push(Mongoose.Types.ObjectId(req.params.id));
                survey.save();
            }
        );



        //responseSet speichern

        var responseSet = new ResponseSet(req.body);
        responseSet.save(function(error, responseSet) {
            if (error || !responseSet) {
                res.json({ error : error });
            } else {

                res.json(responseSet);
            }
        });
    };

 };

А это app.js, который использует index.js:

var Mongoose = require('mongoose');
var db = Mongoose.createConnection('localhost', 'mytestapp');

var SurveySchema = require('./models/Survey.js').SurveySchema;
var Survey = db.model('surveys', SurveySchema);
var UserSchema = require('./models/Survey.js').User;
var User = db.model('user', UserSchema);

var ResponseSetSchema = require ('./models/Survey.js').responseSet;
var ResponseSet = db.model('responseSet', ResponseSetSchema);

var express = require('express')
  , routes = require('./routes')
  , http = require('http')
  , path = require('path')
  , passport = require('passport')
  , pass = require('./config/pass')

  , user_routes = require('./routes/user');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views/app');
//app.engine('html', require('ejs').renderFile);
app.use(express.static(__dirname + '/views/app'));
app.use(express.cookieParser());
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'securedsession' }));
app.use(passport.initialize()); // Add passport initialization
app.use(passport.session()); // Add passport initialization
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.all('/secure', pass.ensureAuthenticated);


app.get('/', function (req, res)
{
    res.render('index.html');
} );

// some more code... 

app.get('/api/secure/userSurveys/:userId', routes.getSurveysForUser(User));

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Надеюсь поможет в борьбе с проблемой! Заранее огромное спасибо!! :)


person superHH    schedule 01.12.2013    source источник
comment
Можете ли вы предоставить код, который сохраняет ваши опросы?   -  person C Blanchard    schedule 01.12.2013
comment
Привет, я отредактировал свой пост. теперь вы можете увидеть, как ссылка на опрос сохраняется в функции addResponse index.js.   -  person superHH    schedule 02.12.2013
comment
Когда вы заполняете опросы пользователей, не могли бы вы передать функцию в save() для проверки ошибок? Прямо сейчас он завершится неудачно, потому что сохранение обрабатывается асинхронно без обратных вызовов. Например. Используйте что-то вроде: - user.save(функция (ошибка, результат) если (ошибка) { console.log(ошибка); });   -  person C Blanchard    schedule 02.12.2013
comment
Спасибо, вечером добавлю. Но пока мне видимо повезло и сейв сработал. Когда я отображаю документ mongodb, я вижу, что user.surveys заполнен идентификаторами опроса. Так что определенно есть идентификаторы, которые должны быть заполнены.   -  person superHH    schedule 02.12.2013
comment
Не могли бы вы взглянуть на мой index.js, где мне нужны схемы? Может, что-то не так?   -  person superHH    schedule 02.12.2013


Ответы (2)


Попробуйте изменить:

surveys: [{type: Schema.ObjectId, ref: 'SurveySchema'}] });

to

surveys: [{type: Schema.Types.ObjectId, ref: 'SurveySchema'}] });

Кроме того, убедитесь, что ваши опросы были отправлены как дочерние в User.surveys.

http://mongoosejs.com/docs/populate.html, здесь в этом разделе рассказывается о вашем требование подробно:

Относится к детям

Однако мы можем обнаружить, что если мы используем объект aaron, мы не сможем получить список историй. Это связано с тем, что никакие сюжетные объекты никогда не «вталкивались» в aaron.stories.

Хорошо, потребовалось довольно много времени, чтобы разобраться в проблеме:

exports.getSurveysForUser = function(User) {
...
};

Пользовательская модель var не вводится в область видимости должным образом. Изменить на:

exports.getSurveysForUser = (function(User) {
...
})(User);

Сигнатура возвращаемой функции для ПО промежуточного слоя не требует передачи модели User, поскольку они повторно инициируются и передаются в коде ПО промежуточного слоя.

В index.js измените это

app.get('/api/secure/userSurveys/:userId', routes.getSurveysForUser(User));

to

app.get('/api/secure/userSurveys/:userId', routes.getSurveysForUser());

Я также прошу вас самостоятельно протестировать свой код и прочитать как можно больше документов. Кроме того, может быть несколько способов достижения ваших целей. Со временем и практикой вы победите их всех. Удачи!

person Nitin...    schedule 01.12.2013
comment
Привет, я пробовал это, но массив все еще пуст... Для этого тестового сценария есть 2 опроса, помещенные как дочерние в user.surveys. Если я сделаю User.findOne(...) и покажу user.surveys, он будет содержать правильные _ids. - person superHH; 01.12.2013
comment
Пожалуйста, просмотрите мой ответ еще раз - person Nitin...; 01.12.2013
comment
Идея неправильно введенных моделей звучит разумно! Когда я изменяю его, как вы описали, функция немедленно выполняется, когда я запускаю сервер узла, поэтому узел выдает эту ошибку: /Users/coding/Documents/surveyapp/server/routes/index.js:231 .findOne({_id: req.params.userId}) ^ TypeError: Невозможно прочитать свойство 'userId' неопределенного в Object.exports.getResponsesForSurvey [как getSurveysForUser] (/Users/coding/Documents/surveyapp/server/routes/index.js:231:38) на Объект.‹анонимно› - person superHH; 01.12.2013
comment
Ошибку нельзя понять, не глядя на index.js/ваш код, который использует экспортированное промежуточное ПО: функция (req, res) - person Nitin...; 01.12.2013
comment
Извините, но я должен спросить еще раз. Я изменил его на route.getSurveysForUser());. Но все же, когда я делаю exports.getSurveysForUser = (function(User) { ... })(User); функция вызывается сразу, когда я запускаю узел. Так что это не помогает ... Я понятия не имею, что изменить, потому что статус-кво пока довольно прост, и особенно вызов заполнения такой же, как в документах. Так что я понятия не имею, что не так, и мне все еще нужна помощь с этим... - person superHH; 02.12.2013
comment
Не могли бы вы взглянуть на мой index.js, где мне нужны схемы? Может, что-то не так? - person superHH; 02.12.2013
comment
Извините, время всегда ограничено, я внимательно просмотрел этот файл, но, не имея возможности запускать и отлаживать, я не в состоянии помочь. Если это очень важно для вас, настройте репозиторий git и свяжите меня с ним. - person Nitin...; 03.12.2013
comment
mongoose.Schema.ObjectId === mongoose.Schema.Types.ObjectId дает истину - person caub; 17.09.2015

Итак, я нашел решение! Сначала казалось, что схемы мангуста не нужны правильно.

Итак, в моделях я сделал mongoose.model('modelname', schemaname); для каждой модели, и теперь я использую mongoose.model(...) только для каждой модели в index.js.

Во-вторых, я узнал о еще более критической вещи: у моего тестового пользователя внезапно больше не было user.surveys! Я уверен, что несколько дней назад он был заполнен опросами. Потому что я тестировал свой код несколько раз, и некоторые опросы были отправлены в эту коллекцию. Может быть, я уронил коллекцию на каком-то тестировании ... я действительно не помню. Поэтому я вручную отправил опрос в консоль mongodb и снова протестировал его --> сработало! опросы пользователей были заполнены! возможно, функция работала вчера и не нуждалась в каких-либо изменениях. Мне очень жаль, если это была пустая трата времени.

Плохо то, что прямо сейчас exports.addResponse(....) только сохраняет ответ, но не передает идентификаторы в массивы user.surveys и Survey.responses. Кажется, это проблема синхронизации, и я как-нибудь это выясню.

В любом случае, спасибо за вашу помощь и время!

person superHH    schedule 02.12.2013