Mongoose deep populating multiple 2nd level objects not working
Asked Answered
G

1

6

I have a model A wit this field :

var field = {
    foo: String,
    b: [{ type: Schema.Types.ObjectId, ref: 'B' }]
}  

and model B with this feilds :

var field = {
    c: { type: Schema.Types.ObjectId, ref: 'C' } // let's say this has 3 string field
    d: { type: Schema.Types.ObjectId, ref: 'D' } // so was this
}

Based on this answer by Trinh Hoang Nhu by doing this-

 A.find({_id:req.params.id})
    .populate({ path: 'patient', model: Patient,
        populate: {
            path: 'b',
            model: B
        },
        populate: {
            path: 'c',
            model: C
        },
    })
    .exec(function (err, doc) {
        res.send(doc);
    })

-it should return the populated 2nd level and it did but the problem is it only populate the last path declared on the .populate({}) function, in this case only the model C is populated. But when you changed it's position with model B then model B will be populated.

The query above returns something like this :

[
    {
        "foo":"Bar",
        "b": [
            {
                "c":"a32s1da4fas1a23s1da56s4c",
                "d":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                }
            },
            {
                "c":"a32s1da4fas1a23s1da56s4d",
                "d":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                }
            }
            // so on ...
        ]
    }
]

I was expecting something like this :

[
    {
        "foo":"Bar",
        "b": [
            {
                "c":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                },
                "d":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                }
            },
            {
                "c":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                },
                "d":{
                    "foo1":"Bar1",
                    "foo2":"Bar2",
                    "foo3":"Bar3"
                }
            }
            // so on ...
        ]
    }
]
Goaltender answered 12/3, 2016 at 11:29 Comment(0)
C
23

I dont know why it even accepted multiple populate keys in the object, it is already duplicated, what you specified to populate is:

 populate: {
            path: 'b',
            model: B
        },
        populate: {
            path: 'c',
            model: C
        },

here the property populate gets duplicated, and only the last one defined is considered.

You need to specify the populate paths once as an array. So your populate property would become:

 populate: [{
            path: 'b',
            model: B
        },{
            path: 'c',
            model: C
        }]

And the query is,

A.find({_id:req.params.id})
    .populate({ path: 'patient', model: Patient,
        populate: [{
            path: 'b',
            model: B
        },{
            path: 'c',
            model: C
        }],
    })
    .exec(function (err, doc) {
        res.send(doc);
    })
Clarisclarisa answered 15/3, 2016 at 7:16 Comment(3)
Oh God! Thanks Naeem! I haven't noticed that.Goaltender
saves me some time!! mongoosejs.com/docs/populate.html#deep-populateTerzas
Big Thanks man ! I was struggling with that use case. I still think that we might avoid using mongoose and rather work with the native nodejs mongodb driver.Hortative

© 2022 - 2024 — McMap. All rights reserved.