0

I am receiving an empty array with the following code:

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

            }
        });
}};

This is the console output:

 [ ]

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

These are the Mongoose models:

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

Btw:

I already tried User.findOne(...) and then a Survey.find() in the callback. It seemed that the second statement was not even executed. Apparently i am very new to mongoose..and i can't find a way around this problem

Do you have any ideas how to help me? I couldn't really find any helpful solution here, but the problem shouldn't be a big one. Thanks in advance, its really keeping me up for days now!!

Edit: So this is the index.js with the method:

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

 };

And this is the app.js, which consumes the 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'));
});

Hope it helpsto fight the problem! Many many thanks in advance!! :)

5
  • Can you provide code that's been saving your surveys? Commented Dec 1, 2013 at 15:05
  • Hi, i edited my post. now you can see how a reference to a survey is saved in the index.js addResponse function. Commented Dec 2, 2013 at 14:00
  • When you populate the user surveys, could you pass a function into save() to check for errors? Right now it will fail silently because the save is being handled asynchronously with no callbacks. E.g. Use something like:- user.save(function (error, result) if (error) { console.log(error); }); Commented Dec 2, 2013 at 15:13
  • Thank you, I will add that tonight. But so far i seem to have been lucky and the save worked. When i display the mongodb document, i see that user.surveys is filled with the survey IDs. So there are definitely IDs, that should be "populateable".. Commented Dec 2, 2013 at 16:30
  • Could you please have a look at my index.js, where i require the Schemas? Maybe there is something wrong? Commented Dec 2, 2013 at 19:24

2 Answers 2

1

Try changing:

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

to

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

Also, make sure you have surveys pushed as children to User.surveys.

http://mongoosejs.com/docs/populate.html, here this section talks about your requirement in detail:

Refs to children

We may find however, if we use the aaron object, we are unable to get a list of the stories. This is because no story objects were ever 'pushed' onto aaron.stories."

Ok, it took quite a lot to figure out the issue:

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

The var User - model is not being injected into the scope properly. Change to:

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

The returned function's signature for middleware do not require User model to be passed as they are re-initiated and passed within the middleware code.

In index.js, change this

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

to

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

I also request you to self test your code and read as many docs as possible. Also, there can be multiple ways of reaching your goals. With time and practice you will conquer them all. Good luck!

Sign up to request clarification or add additional context in comments.

8 Comments

Hi, i tried that, but the array is still empty... For this test szenario, there are 2 surveys pushed as children to user.surveys. If i do a User.findOne(...) and display the user.surveys, it contains the correct _ids.
Please review my answer again
The idea of not properly injected models sounds reasonable! When i change it like you described, the function is immediately executed when i start the node server, so node throws this error: /Users/coding/Documents/surveyapp/server/routes/index.js:231 .findOne({_id: req.params.userId}) ^ TypeError: Cannot read property 'userId' of undefined at Object.exports.getResponsesForSurvey [as getSurveysForUser] (/Users/coding/Documents/surveyapp/server/routes/index.js:231:38) at Object.<anonymous>
The error cannot be understood without looking at the index.js/your code that consumes the hence exported middleware: function (req, res)
Sorry, but i have to ask again. I changed it to routes.getSurveysForUser());. But still, when i do exports.getSurveysForUser = (function(User) { ... })(User); the function is called immediately when i start node. So that's not helping.. I have no clue what to change, because the status quo is pretty simple so far and especially the populate call is just like in the docs. So I have no idea whats wrong and I still need help with that...
|
1

So i found a solution! Firstly it seemed, that the mongoose Schemas were not correctly required.

So in the models, i did mongoose.model('modelname', schemaname); for every model and now i only use mongoose.model(...) for every model in the index.js.

Secondly i found out about an even more critical thing: There were suddenly no user.surveys for my testuser anymore! I am sure that it was filled with surveys a few days ago. Because i tested my code several times and some surveys were pushed to that collection. Maybe i dropped the collection it in some testing..i don't really remember. So i pushed a survey manually in the mongodb console and tested it again --> worked! the user.surveys were populated! maybe the function worked yesterday and didn't need any change. I am so sorry, if that was a waste of time.

Bad thing is, that right now the exports.addResponse(....) is only saving a response, but is not pushing the IDs to the arrays user.surveys and survey.responses. This seems to be a synchronizing Problem and i will figure that out somehow.

Anyways, thank you for your help and time!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.