Calling populate on embedded doc of embedded doc
Problem
Hey, I have the following schemas ( simplified for issue) User = new Schema login:String A = new Schema emb: [B] comments: [Comments] //and following embedded schemas B = new Schema comments: [Comments] Comments = new Schema creator: type: ObjectId ref: 'User' message: String Now while populate works on A eg A.find().populate('comments.creator') it doesn't work on the double nested embedded doc eg A.find().populate('emb.comments.creator') Any ideas?
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Fix Double Nested Population in Mongoose
Mongoose does not support population on deeply nested embedded documents directly. The populate method works on top-level documents and their immediate references, but for nested arrays, you need to manually handle the population logic.
Awaiting Verification
Be the first to verify this fix
- 1
Flatten the Schema Structure
Consider restructuring your schemas to avoid deep nesting. Instead of embedding comments within B, you can reference them directly in A or use a different approach to manage the relationships.
javascriptconst A = new Schema({ emb: [{ type: Schema.Types.ObjectId, ref: 'B' }], comments: [{ type: Schema.Types.ObjectId, ref: 'Comments' }] }); - 2
Use Aggregation Framework for Nested Population
If restructuring is not feasible, use MongoDB's aggregation framework to perform a lookup on the nested documents. This allows you to join the collections and retrieve the necessary data.
javascriptA.aggregate([{ $unwind: '$emb' }, { $lookup: { from: 'bs', localField: 'emb', foreignField: '_id', as: 'embDetails' } }, { $unwind: '$embDetails' }, { $lookup: { from: 'comments', localField: 'embDetails.comments', foreignField: '_id', as: 'commentsDetails' } }]) - 3
Manual Population of Nested Documents
If aggregation is too complex for your use case, manually retrieve the documents and populate them in your application logic. Fetch A, then for each embedded B, fetch the comments separately.
javascriptconst aDocs = await A.find().populate('comments.creator'); for (let aDoc of aDocs) { for (let emb of aDoc.emb) { emb.comments = await Comments.find({ _id: { $in: emb.comments } }).populate('creator'); } } - 4
Test the Changes
Run your application and test the queries to ensure that the comments for each embedded document are being populated correctly. Check for any errors or unexpected results.
Validation
Confirm the fix by running the modified queries and checking that the comments for each embedded document are populated correctly. Ensure there are no errors and that the data structure matches expectations.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep