2

I have challenge here where I am trying to populate a subdocument from another subdocument which is in same collection. Is this possible?Below is example schemas I have

var chapter = new Schema({
  title:String,
  startPage:Number,
  endPage:Number
});


var keyPoint = new Schema({
  text:String,
  mentionInChapter:[{
      type: Schema.ObjectId,
      ref: 'chapter'}]
});


var Book = new Schema({
   title:String,
   author:String,
   chapters:[chapter],
   keyPoints:[keypoint]
});

I tried below and it did not populate the chapterId in keyPoints array.

Book.findById(id).populate('chapter').exec(function(err,doc){ if(!err) console.log(doc); });

Is there a way to achieve this so that Book document I retrieve has all the details populated?

Shambu
  • 2,612
  • 1
  • 21
  • 16

1 Answers1

0

You can try to use Model.populate method something like the following:

var chapter = new Schema({
  title:String,
  startPage:Number,
  endPage:Number
});

var keyPoint = new Schema({
  text:String,
  mentionInChapter:[{type: Schema.ObjectId, ref: 'chapter'}]
});

var Book = new Schema({
   title:String,
   author:String,
   chapters:[chapter],
   keyPoints:[keyPoint]
});

Book.findById(id)
   .lean()
   .populate('chapters keyPoints')
   .exec(function (err, docs) {
      if (err) throw err;

      Book.populate(docs, {path: 'keyPoints.mentionInChapter'}, function (err, book) {
         if (err) throw err;

         console.log(book);
      });
   });

UPDATE: Version 2:

var chapter = new Schema({
  title:String,
  startPage:Number,
  endPage:Number
});

var keyPoint = new Schema({
  text:String,
  mentionInChapter:[{type: Schema.ObjectId, ref: 'chapter'}]
});

var Book = new Schema({
   title:String,
   author:String,
   chapters:[chapter],
   keyPoints:[keyPoint]
});

Book.findById(id).exec(function (err, doc) {
   if (err) throw err;

   Book.populate(doc, {path: 'keyPoints.mentionInChapter'}, function (err, book) {
      if (err) throw err;

      console.log(book);
   });
});
  • Thanks Artem. In above solution you have made chapter and keypoint as separate documents than embedded documents. Keypoint would make me sense as this would increase in size. But wondering if I am going to retrieve chapters always with Book, should i need to make it also a separate document collection? – Shambu Aug 08 '15 at 18:32
  • mongoose `populate` is very flexible, so you could try out my examples and choose one that most useful for your case. – Artem Baranovskii Aug 08 '15 at 19:27
  • Thanks Artem once again for quick reply. If I run the version 2, i get blank array for mentionInChapter. and there are no errors thrown. So still it is not populating. the Path keyPoints is an array. So not sure if this path keyPoints.mentionInChapter is expected to work? – Shambu Aug 08 '15 at 20:18
  • It should. There are examples where people resolve the same task http://stackoverflow.com/questions/19222520/populate-nested-array-in-mongoose#answer-19227709 Try to add `model` option to populate config – Artem Baranovskii Aug 08 '15 at 20:25
  • Tried with both model as 'chapter' or model as 'keyNote', still the same result. The data in mongodb is as per this gist - https://gist.github.com/sham332/20ad1c7b1b460c478700. Wondering if I am storing data in wrong way? – Shambu Aug 08 '15 at 20:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/86527/discussion-between-artem-baranovskii-and-sham332). – Artem Baranovskii Aug 08 '15 at 20:48