Mongoose Populate 返回空数组

Posted

技术标签:

【中文标题】Mongoose Populate 返回空数组【英文标题】:Mongoose Populate returns empty array 【发布时间】:2013-12-17 06:55:45 【问题描述】:

我收到一个包含以下代码的空数组:

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: 'a@b.de',
  password: '202cb962ac59075b964b07152d234b70',
  surveys: []

这些是猫鼬模型:

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

希望它有助于解决问题! 非常感谢提前! :)

【问题讨论】:

您能提供保存调查的代码吗? 嗨,我编辑了我的帖子。现在您可以看到对调查的引用是如何保存在 index.js 的 addResponse 函数中的。 当您填充用户调查时,您可以将函数传递给 save() 以检查错误吗?现在它会默默地失败,因为保存是异步处理的,没有回调。例如。使用类似:- user.save(function (error, result) if (error) console.log(error); ); 谢谢,今晚我会补充的。但到目前为止,我似乎很幸运,并且保存成功。当我显示 mongodb 文档时,我看到 user.surveys 填充了调查 ID。所以肯定有 ID,应该是“可填充的”.. 能否请您看一下我的 index.js,我在哪里需要 Schemas?也许有什么问题? 【参考方案1】:

尝试改变:

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

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

此外,请确保您已将调查推送到 User.surveys

http://mongoosejs.com/docs/populate.html,本节在这里详细谈谈您的要求:

参考儿童

然而,我们可能会发现,如果我们使用 aaron 对象,我们将无法获得故事列表。这是因为没有故事对象被‘推送’到 aaron.stories 上。”

好的,花了很多时间才弄清楚这个问题:

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

var User - 模型未正确注入作用域。改为:

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

返回的中间件函数签名不需要传递User模型,因为它们在中间件代码中重新启动并传递。

在 index.js 中,改变这个

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

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

我还要求您自行测试您的代码并阅读尽可能多的文档。此外,可以有多种方式来实现您的目标。随着时间和练习,您将征服所有这些。祝你好运!

【讨论】:

嗨,我试过了,但数组仍然是空的......对于这个测试场景,有 2 个调查作为孩子推送到 user.surveys。如果我执行 User.findOne(...) 并显示 user.surveys,它包含正确的 _ids。 请再次查看我的回答 未正确注入模型的想法听起来很合理!当我像您描述的那样更改它时,该功能会在我启动节点服务器时立即执行,因此节点会抛出此错误:/Users/coding/Documents/surveyapp/server/routes/index.js:231 .findOne(_id: req.params.userId) ^ TypeError:无法读取 Object.exports.getResponsesForSurvey [as getSurveysForUser] (/Users/coding/Documents/surveyapp/server/routes/index.js:231:38) 处未定义的属性“userId”在 Object. 如果不查看使用因此导出的中间件的 index.js/您的代码,则无法理解该错误:function (req, res) 对不起,我得再问一次。我将其更改为 routes.getSurveysForUser());。但是,当我执行 export.getSurveysForUser = (function(User) ... )(User);当我启动节点时立即调用该函数。所以这没有帮助..我不知道要改变什么,因为到目前为止现状非常简单,尤其是 populate 调用就像在文档中一样。所以我不知道出了什么问题,我仍然需要帮助......【参考方案2】:

所以我找到了解决方案! 首先,mongoose Schema 似乎不是正确需要的。

所以在模型中,我做了 mongoose.model('modelname', schemaname);对于每个模型,现在我只对 index.js 中的每个模型使用 mongoose.model(...)。

其次,我发现了一件更关键的事情:我的 testuser 突然没有 user.surveys 了!我敢肯定,几天前它充满了调查。因为我多次测试了我的代码,并且一些调查被推送到该集合中。也许我在一些测试中放弃了它的收藏......我真的不记得了。因此,我在 mongodb 控制台中手动推送了一项调查并再次对其进行了测试-> 成功了! user.surveys 已填充!也许该功能昨天有效,不需要任何更改。很抱歉,如果那是浪费时间。

糟糕的是,现在exports.addResponse(....) 只是保存一个响应,而不是将ID 推送到数组user.surveys 和survey.responses。这似乎是一个同步问题,我会以某种方式解决这个问题。

无论如何,感谢您的帮助和时间!

【讨论】:

以上是关于Mongoose Populate 返回空数组的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose populate() 返回空数组

Mongoose populate() 返回没有错误的空数组

Mongoose Populate Child ref 返回空数组

mongoose#populate 在数组内的嵌套对象中返回 null

Mongoose .populate 随机

19-3-18 mongoose 连表查询populate用法