KoderSolutionKoderSolution LogoKoderSolution Logo
HomeArticlesTutorialsToolsRun CodeForumAI Lab
🟢

Node.js

Topic Hub & Articles

Node.js Intro

10 min

Node.js Get Started

10 min

Node.js Modules

10 min

Node.js HTTP Module

10 min

Node.js File System

10 min

Node.js URL Module

10 min

Node.js NPM

10 min

Node.js Events

10 min

Node.js Upload Files

10 min

Node.js Email

10 min

Node.js Buffer

10 min

Recap Quiz

Gated

Milestone Assessment

Node.js Streams

10 min

Node.js Crypto

10 min

Node.js OS Module

10 min

Node.js Path Module

10 min

Node.js Global Objects

10 min

Recap Quiz

Gated

Milestone Assessment

Node.js Process

10 min

Node.js Child Processes

10 min

Node.js Worker Threads

10 min

Node.js DNS Module

10 min

Node.js Query String

10 min

Recap Quiz

Gated

Milestone Assessment

MySQL Connect

10 min

MySQL Create Database

10 min

Recap Quiz

Gated

Milestone Assessment

Node.js MySQL ORDER BY Clause

10 min

Recap Quiz

Gated

Milestone Assessment

MongoDB Intro

10 min

MongoDB Create Database

10 min

MongoDB Create Collection

10 min

MongoDB Insert

10 min

Recap Quiz

Gated

Milestone Assessment

MongoDB Find

10 min

MongoDB Query

10 min

MongoDB Sort

10 min

MongoDB Delete

10 min

MongoDB Update

10 min

Recap Quiz

Gated

Milestone Assessment

MongoDB Limit

10 min

MongoDB Join

10 min

Progress
0%

0 / 35 Lessons

KoderSolutionKoderSolution LogoKoderSolution Logo

The world’s most advanced technical ecosystem for modern software engineers. Learn, build, and grow with next-generation developer tools and resources.

Facebook PageX (Twitter) ProfileYouTube ChannelContact Support

Engineering Newsletter

Subscribe for weekly software engineering tutorials, architecture guides, and developer tool updates.

Platforms

  • Technical Articles
  • Interactive Tutorials
  • AI Coding Lab
  • Developer Forum
  • Developer Tools

Pages

  • About Us
  • Contact Us
  • Privacy Policy
  • Terms of Service
  • Refund Policy
  • Disclaimer
  • Advertisement

Popular Topics

  • PHP
  • Laravel
  • Python
  • React.Js
  • MySQL
© 2026 KoderSolutionAll Rights Reserved
Developed Bymaksudur.dev
Node.jsNode.js MongoDB
Lesson

MongoDB Join

10 min reading
Free Course

MongoDB Join in Node.js: Aggregation Pipelines with $lookup

Although MongoDB encourages embedding tightly coupled data inside one document, normalized references (like orders.userId pointing to users._id) still appear often. MongoDB joins documents across two collections on the database server using the $lookup stage inside collection.aggregate().

Joining Collections with $match, $lookup, and $unwind

Place $match at the very start of your pipeline so MongoDB filters records using indexes before joining. After $lookup attaches an array of matching child documents, $unwind (with preserveNullAndEmptyArrays: true for left-join behavior) flattens single matches into an object, and $project keeps only safe fields.

flowchart LR
    A["orders ($match status: paid)"] --> B["$lookup from: users"]
    B --> C["$unwind customer (preserveNull)"]
    C --> D["$project safe response fields"]
async function listOrdersWithCustomers(ordersCollection) {
  const pipeline = [
    { $match: { status: 'paid' } },
    { $sort: { createdAt: -1 } },
    { $limit: 20 },
    {
      $lookup: {
        from: 'users',
        localField: 'userId',
        foreignField: '_id',
        as: 'customer',
      },
    },
    {
      $unwind: {
        path: '$customer',
        preserveNullAndEmptyArrays: true,
      },
    },
    {
      $project: {
        _id: 1,
        totalAmount: 1,
        createdAt: 1,
        customerName: '$customer.fullName',
        customerEmail: '$customer.email',
      },
    },
  ];

  return ordersCollection.aggregate(pipeline).toArray();
}

Keeping $lookup Fast in Production

Always create an index on foreignField in the target collection (users._id is already indexed, while comments.postId needs an explicit index) so $lookup does not scan the entire foreign collection for every input document.

Common Mistakes to Avoid

  • Omitting preserveNullAndEmptyArrays: true on $unwind: By default, $unwind: '$customer' silently drops any order whose customer array is empty (acting like an INNER JOIN instead of a LEFT JOIN).
  • Putting $match and $limit after $lookup: Joining 100,000 orders before filtering down to 20 paid rows wastes enormous CPU and memory. Filter and limit as early as possible.
  • Exposing passwordHash from the joined users document: Always add a $project stage (or pipeline inside $lookup) to strip sensitive fields.

Frequently Asked Questions

Can $lookup filter or sort the joined collection before returning it?

Yes. Using the pipeline syntax inside $lookup with let variables lets you run $match, $sort, $limit, and $project directly on the joined collection.

When should I embed sub-documents vs using $lookup?

Embed data that is bounded and always read together (like shipping address or invoice line items). Reference by ID and join with $lookup when the child collection grows unboundedly or is shared across many records (like users or products).

Does $lookup work with sharded collections?

Yes, modern MongoDB versions support $lookup on sharded collections, though co-locating or embedding hot read paths remains faster at very high scale.

Save Your Progress

Unlock Your
Full Potential.

Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.

Quick Access With

Enterprise-Grade Security Protocol

Try it Yourself

Experiment with the code from this lesson in our interactive playground.

Open Playground

Related Developer Tools & Topic Hub

Node.js Topic Hub
JSON Formatter
Validate, format, and minify JSON
Regex Tester
Test regular expression patterns
JWT Decoder
Inspect JSON Web Token payloads
All Node.js Articles
Deep-dive guides, tips & discussions
PreviousMongoDB Limit
Continue JourneyComplete Topic

Stuck on this lesson?

Join our community of senior developers.

Ask in Forum