SyntaxStudy
Sign Up
MongoDB Population with $lookup
MongoDB Beginner 1 min read

Population with $lookup

When you model relationships using references, you need to join data at query time. In the aggregation pipeline, $lookup performs this join server-side and is the recommended approach for complex queries. For simpler cases in application code, you can fetch the parent document and then issue a second query for the children using $in on an array of IDs. This "application-side join" is sometimes faster than $lookup when the referenced collection is large and well-indexed, because you have more control over the query plan. Always benchmark both approaches for your data size and access pattern before committing to one.
Example
// $lookup: join posts with their authors
db.posts.aggregate([
  { $match: { published: true } },
  { $lookup: {
      from:         "users",
      localField:   "authorId",
      foreignField: "_id",
      as:           "authorDoc"
  }},
  { $unwind: "$authorDoc" },
  { $project: {
      title:       1,
      publishedAt: 1,
      "author.name":   "$authorDoc.name",
      "author.avatar": "$authorDoc.avatar"
  }}
])

// Application-side join (two queries)
const post = await db.collection('posts').findOne({ slug: "my-post" })
const author = await db.collection('users').findOne({ _id: post.authorId })
const fullPost = { ...post, author }

// Fetch multiple referenced docs with $in
const postList = await db.collection('posts').find({}).toArray()
const authorIds = postList.map(p => p.authorId)
const authors   = await db.collection('users')
  .find({ _id: { $in: authorIds } })
  .toArray()
const authorMap = Object.fromEntries(authors.map(a => [a._id.toString(), a]))