无法在另一个模型中引用/填充mongoose模型

时间:2016-01-06 22:24:50

标签: javascript node.js mongoose mongoose-populate mongoose-schema

背景:允许用户发布投票民意调查的应用程序 我在用户模型中填写对Polls模型的引用时遇到了一些麻烦。我正在使用mongoose.populate来尝试填充民意调查。在我的路由中,populate函数无法正常工作(返回的用户为null)。这是我的模特......

users.js:

// models/users.js

var mongoose = require('mongoose'),
    Poll = require('./poll');

//define the schema for our user model
var userSchema = mongoose.Schema({
    local:{
        email: String,
        password: String,
        name: String
    },
    twitter:{
        id: String,
        token: String,
        name: String
    },
    polls:[{type: mongoose.Schema.Types.ObjectId, ref:'Poll'}]
});

poll.js:

//load mongoose
var mongoose = require('mongoose'),
    User = require('./user');


var pollSchema = mongoose.Schema({
       name:String,
       options:[String],
       creator: {type:mongoose.Schema.Types.ObjectId, ref:'User'}
});


module.exports = mongoose.model('Poll', pollSchema);

这是我要在...中实施人口的路线。

 //require user and poll model 
 var User = require('../models/user'),
 Poll = require('../models/poll');

 app.post('/dashboard', isLoggedIn, function(req,res){ 

    var poll = {name: req.body.name, 
                options: req.body.option, 
                creator: req.user.local.id};

    //create new poll 
    var newPoll = new Poll();
    newPoll.polls = poll;

    //find the user with the request id and populate polls reference in User (UserSchema)
    User.findById(req.user.local.id)
         .populate('polls')
          .exec(function(err,user){ // cant figure this out...

              if(err){return err;}

              console.log(user); // yields null

              res.send({success:true, message: "Post Successful!"});

           });        
     });

任何帮助,建议,想法将不胜感激。感谢。

2 个答案:

答案 0 :(得分:1)

Mongoose中的人群是一个很棒的特征。从我在您的代码中看到的内容来看,您似乎无法为用户分配池。您的第一部分引用了用户内部的池,但没有引用池内用户的第二部分,并且mongoose需要两者来执行操作。

我认为您希望池具有名称和选项列表。我在代码中可以看到的是一个包含池数组的池,因此我更改了池模式以适合您的解释。

尝试使用此新池模式添加对池中用户的引用:

pools.js

var mongoose = require('mongoose');

var pollSchema = mongoose.Schema({
       name:String,
       options:[String],
       creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});


module.exports = mongoose.model('Poll', pollSchema);

现在,在保存游泳池时,请不要忘记添加您的用户参考。您正在为用户填充池,因此在mongoose回调中传递的对象将不是池列表,而是您要查找的用户。感谢人口,您将在属性pools中获取对象列表而不是ID列表。

 var User = require('../models/user'),
 Poll = require('../models/poll');

 app.post('/dashboard', isLoggedIn, function(req,res){ 

    var poll = {
       name: req.body.name, 
       options: req.body.option, 
       creator: req.user.local.id
     };

    var newPoll = new Poll();
    newPoll.polls = poll;

    User.findById(req.user.local.id)
         .populate('polls')
          .exec(function(err, user){
           /*
             You should get in user object something like:
             {
               local: {...},
               twitter: {...},
               pools: [{
                 name: 'Pool1',
                 options: [...]
               }]
              }
           */
           });        
     });
});

答案 1 :(得分:1)

在您提交的代码中,您永远不会明确创建User

有两种方法可以处理你想做的事情,一种比另一种更好,我会解释原因。

您可以向用户模型添加一系列轮询:

var userSchema = new mongoose.Schema({
    local:{
        email: String,
        password: String,
        name: String
    },
    twitter:{
        id: String,
        token: String,
        name: String
    },
    polls:[{type: mongoose.Schema.Types.ObjectId, ref:'Poll'}]
});

请注意,您应该指定userSchema = mongoose.Schema。

如果这是您的选择,那么当您创建新的Poll实例时,您必须创建Poll,检索相应的用户(User.findById),然后将Poll._id推送到user.polls,并保存用户。
这种方法允许您在检索用户对象时简单地调用.populate('polls')以获取结果集中的所有用户轮询。

或者,您可以将轮询数组保留在User模型之外,只需在Poll模式中创建引用:

var pollSchema = new mongoose.Schema({
       name:String,
       options:[String],
       creator: {type:mongoose.Schema.Types.ObjectId, ref:'User'}
});

再次注意您应该使用 new 和mongoose.Schema声明。

如果采用这种方法,则只需在创建时将user._id添加到poll对象中。

如果您愿意,您可以在检索民意调查时检索用户:

Poll.findById(...however you are retrieving your Poll id...)
         .populate('creator')
          .exec(function(err, poll){....

如果您想列出给定用户发布的所有民意调查,只需执行以下操作:

Poll.find({"creator": req.params.userId})
    .populate('creator')
    .exec(function(err, poll) {
        if(err) return err;
        res.json(poll);
    };

以上代码中的req.params.userId不应被视为文字,并且取决于您的应用如何检索用户ID,同样响应返回方法取决于您的特定应用,它上面的代码返回用户创建的轮询数组作为json对象。

第二种方法可能更好,原因之一是它避免了文档膨胀。 我似乎没有足够的声誉来评论或降级之前的答案,但严重的是,这是不正确的。 您绝对不需要在用户架构中使用民意调查数组,并且民意调查中的用户(创建者)可以解析填充调用。

每当你有一个没有边界的模型模式引用的数组(用户可以创建他们想要的多个民意调查)时,你的数据库中每个用户文档的大型系统都会变得巨大......对于用户创建的每个民意调查,您在民意调查集合中添加新的民意调查文档,并且您正在增加父用户文档的大小。

你基本上存储了两次相同的信息。用任何数据库进行练习。

如果您的父对象仅限于它可以拥有的子对象数,例如用户在编程上限于创建3个轮询,那么您可以将该数组添加到用户模型。

但是,如果对孩子的成长没有强制限制,假设用户可以创建他们想要的任意数量的民意调查,那么我建议你在用户模式中没有一个民意调查数组,而是有一个创建者在Poll架构中引用创建用户。

在任何一种情况下,做一个或另一个,而不是两个...在任何一种情况下都有一种有效的方法来获取关系的数据而不将关系存储在两个不同的文档中。