问题
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: 'a@b.de',
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!! :)
回答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!
回答2:
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!
来源:https://stackoverflow.com/questions/20313517/mongoose-populate-returns-empty-array