rsilva
rsilva

Reputation: 270

Aggregate and lookup

I am trying to group a mongoose query and populate a few sub-documents in mongoose using $lookup but my result document arrays are returning empty. Can anyone tell me why?

var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

var answerSchema = new Schema({
  _user               : { type: Schema.Types.ObjectId, ref: 'User', required: true },
  _poll               : { type: Schema.Types.ObjectId, ref: 'Poll', required: true },
  _question           : [{ type: Schema.Types.ObjectId, ref: 'Question' }],
  answer              : { type : String },
  },
  { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } 
});

mongoose.model('Answer', answerSchema);

Here's my code:

module.exports = {

  index: function(req, res, next){

    Poll.findOne({_id: req.params.poll_id}, function(err, poll){
    if(err) return next(err);

    console.log(poll);

    Answer.aggregate([
        {$unwind: "$_question"},
        {$match: {_poll: poll._id}},
        {$group: {
            _id: '$_question',
        }},
        {
          $lookup : { 
            from : 'polls', 
            localField : '_poll', 
            foreignField: '_id', 
            as: 'poll' 
          },
        },
        {
          $lookup : { 
            from : 'questions', 
            localField : '_question', 
            foreignField: '_id', 
            as: 'questions'   
          },
        },
        {
          $lookup : { 
            from : 'users', 
            localField : '_user', 
            foreignField: '_id', 
            as: 'user' 
          },
        },
    ], function (err, result) {
         res.status(200).json(result);
    });

    });
  },

The new subdocuments are returned empty for some reason. Please note that each answer contains the reference to ONE poll, ONE user and MANY questions.

[
{
_id: "57ce8927ea5a4f090774215d",
poll: [ ],
questions: [ ],
user: [ ]
}
]

Can anyone spot my mistake?

Should I be using $project instead? I heard $lookup is the new and better way. I am using mongo 3.2.0 and mongoose 4.5.8.

Upvotes: 0

Views: 1139

Answers (1)

Ananth Pai
Ananth Pai

Reputation: 1969

Mongdb aggregate query is a pipeline operation. So the result of subsequent queries is passed on to the next query. For more info on Mongodb aggregate refer this. The mistake you have done is that when you used the $group query only _id is being passed on to the next $lookup query. You can fix this by using the following query.

Answer.aggregate([
    {$unwind: "$_question"},
    {$match: {_poll: poll._id}},
    {$group: {
        _id: '$_question',
        _poll: { $first: '$_poll'},
        _user: { $first: '$_user'},
        _question : { $first: "$_question "}
    }},
    {
      $lookup : { 
        from : 'polls', 
        localField : '_poll', 
        foreignField: '_id', 
        as: 'poll' 
      },
    },
    {
      $lookup : { 
        from : 'questions', 
        localField : '_question', 
        foreignField: '_id', 
        as: 'questions'   
      },
    },
    {
      $lookup : { 
        from : 'users', 
        localField : '_user', 
        foreignField: '_id', 
        as: 'user' 
      },
    },
], function (err, result) {
     res.status(200).json(result);
});

Upvotes: 1

Related Questions