Home > Blockchain >  Mongoose: popluate level 2 child object
Mongoose: popluate level 2 child object

Time:01-03

I have the following code in a file "test.js", in which I am trying to populate story.fans[0].stories[0] , but it doesn't work. The rest of the code runs fine, but when it is trying to populate fan[0]'s child object stories, it doesn't seem to work. Can mongoose popluate 2 level child objects?

const mongoose = require('mongoose');

main().catch(err => console.log(err));

async function main() {
  await mongoose.connect('mongodb://localhost:27017/testMongoose');


const Schema = mongoose.Schema;

const personSchema = Schema({
  _id: Schema.Types.ObjectId,
  name: String,
  age: Number,
  stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

const storySchema = Schema({
  author: { type: Schema.Types.ObjectId, ref: 'Person' },
  title: String,
  fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});

const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);
Story.
    findOne({ title: 'Casino Royale' }).populate('fans').
    exec(function (err, story) {
      if (err) return handleError(err);
      console.log('the story is',story.title);
      console.log('The fans[0] is %s', story.fans[0].name);
      story.fans[0].populate('stories');
      console.log('the story written by fan is',story.fans[0].stories[0].title);
//option2
story.fans[0].populate('stories').exec(function(err,fan){
  console.log('the story written by fan is',fan.stories[0].title);
});

    });
}

Here is the error message: enter image description here

---------------- This is my stories collection:

   /* 1 */
    {
        "_id" : ObjectId("61cfd221256ef6d903523700"),
        "author" : ObjectId("61cfd221256ef6d9035236fe"),
        "title" : "Casino Royale",
        "fans" : [ 
            ObjectId("61cfee8b5059fb3fe37b3c5f")
        ],
        "__v" : 1
    }
    
    /* 2 */
    {
        "_id" : ObjectId("61d09887abeb41f82a7e1678"),
        "author" : ObjectId("61cfee8b5059fb3fe37b3c5f"),
        "title" : "Story 001",
        "fans" : [],
        "__v" : 0
    }

This is my people collection

  /* 1 */
{
    "_id" : ObjectId("61cfd221256ef6d9035236fe"),
    "name" : "Ian Fleming",
    "age" : 50,
    "stories" : [],
    "__v" : 0
}

/* 2 */
{
    "_id" : ObjectId("61cfee8b5059fb3fe37b3c5f"),
    "name" : "Fan 001",
    "age" : 38,
    "stories" : [ 
        ObjectId("61d09fbfbd8f3fa20beaa616")
    ],
    "__v" : 14
}

CodePudding user response:

Considering the data provided by you, there is nothing in layer 2 to be populated, since the referenced id in Fan 001 is not matching with any of the stories.

Fans stories:
61d09fbfbd8f3fa20beaa616
==> is not found in
Available stories:
61d09887abeb41f82a7e1678
61cfd221256ef6d903523700

But if you fix your references what you want to be using is called deep Population

You basically populate a field in the object you just populated.

Your code then looks like this:

Story.findOne({ title: 'Casino Royale' })
            .populate({ path: 'fans', model: 'Person', populate: { path: 'stories', model: 'Story' } }).
            exec(function(err, story) {
                if (err) return handleError(err);
                console.log(story)
                console.log('the story is', story.title);
                console.log('The fans[0] is %s', story.fans[0].name);
                console.log('the story written by fan is', story.fans[0].stories[0].title);

            });

I rebuild the example but fixed the references and the output now looks like expected:

enter image description here

  • Related