Search code examples
mongodbmongoosemongoose-schemamongoose-populate

Is populate implicit and how many levels deep can it go?


I have been tasked to modify an existing (large) node.js web using mongoose.

The schema has a Question which links to an array of Answer as follows:

var QuestionSchema = mongoose.Schema({
   text: { type: String },
   ...
   answers: [{type: mongoose.Schema.Types.ObjectId, ref: 'Answer'}],
   ...
});

var AnswerSchema = mongoose.Schema({
   text: { type: String },
   ....
   question: {
      type: mongoose.Schema.ObjectId,
      ref: Question
   },
...
});     
var Question  = mongoose.model('Story', QuestionSchema);
var Answer = mongoose.model('Answer', AnswerSchema);

I couldn't locate any instance of the populate method being used in the code, but a query of a Question document always return with the array of full answer objects, not just the object id. This is what is needed.

I now have to add an array of reaction objects to answer. I used the following:

var Answer = mongoose.model('Answer', AnswerSchema);
var ReactionSchema = mongoose.Schema({
    text: { type: String },
    .... 
    answer: {
        type: mongoose.Schema.ObjectId,
        ref: Answer,
       //required: true
    },
    ...
});

I then added the following to the Answer schema:

reactions: [{type: mongoose.Schema.Types.ObjectId, ref: 'Reaction'}]
//where var Reaction  = mongoose.model('Reaction', ReactionSchema);

I am able to save reaction objects, and when I inspected the database contents of answer, the reaction objects are the same in type and form to answer objects in question.

However, when a question document is returned, each element of answer.reaction contains just the object id of reaction instead of the full reaction object. What have I omitted or how do I make the query to perform the join based on the ref type?

The mongodb version is 3.2.9, and mongoose is 4.0.4.


Solution

  • How do you query a Question? This is how you can resolve nested references:

    Question.findById(id).populate({
      path: 'answer',
      model: 'Answer',
      populate: {
        path: 'reaction',
        model: 'Reaction'
      }
    }).exec(function(err, data){});
    

    Here is the link to the mongoose docs: Mongoose Docs Deep Populate