Search code examples
javascriptnode.jsmongoosemongoose-populatemongoose-schema

Trouble referencing/populating a mongoose model in another model


Background: App that allows users to post voting polls.
I am having a little trouble populating my reference to my Polls model in the User model. I am using mongoose.populate to try and populate the polls. In my route, the populate function is not working correctly (the returned user is null). Here are my models...

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

This is the route that I am going to implement the population in ...

 //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!"});

           });        
     });

Any help, advice, ideas would be greatly appreciated. Thanks.


Solution

  • Populations in Mongoose are such a great feature. From what I saw in your code, you don't seem to assign pools to users. You have the first part that references pools inside users but not the second part which references user inside pools and mongoose needs both to perform the operation.

    I think you want pools to have a name and list of options. The one I can see in your code is a pool containing an array of pools so I changed the pool schema to fit your explanations.

    Try to add a reference to the user in your pools with this new pool schema:

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

    Now, when saving a pool, don't forget to add your user reference. You're populating pools on a user so the object passed in the mongoose callback will not be a list of pools but the user you want to find. Thanks to population, you'll get in the attribute pools a list of objects instead of a list of ids.

     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: [...]
                   }]
                  }
               */
               });        
         });
    });