$lookup for collection joins
coreintermediate$lookup is an aggregation stage that joins documents from another collection into the current one, attaching the matches as a new array field. It is how MongoDB reaches across collections when embedding was not chosen for that relationship.
Think of it as
It plays the same role a SQL LEFT OUTER JOIN plays — for each input document, find the matching documents in another collection and attach them — but the result always lands as an array field on the input document rather than flattened rows, because MongoDB's document model has no row-level join output shape.
What we're doing: Attach each order's customer document as a single-element array field.
- 2
- from names the foreign collection; localField/foreignField say which fields must be equal for a match.
- 6
- as names the new array field the matches land in — "customer" here, even though at most one match exists per order.
Why this works: $lookup always produces an array on as, whether zero, one, or many documents matched — that is the uniform output shape a pipeline-based join needs, since the number of matches is not known ahead of time.
Expecting customer to be a single object because there is only ever one matching customer
Wrong
Better
What you see: Code reading .name directly off the joined field gets undefined, because the field is an array even when it holds exactly one element.
Why: $lookup's output is always an array field, regardless of how many documents matched — one-to-one relationships still need either an array index or an $unwind to reach the single joined document directly.
- orders — local collection
- leads to $lookup (localField)
- $lookup — match customerId = _id
- leads to order + customer[] (attaches as array)
- customers — foreign collection
- leads to $lookup (foreignField)
- order + customer[] — array field, even if 0 or 1 match
Remember: $lookup is a left outer join across collections — every input document survives, matches always land as an array field, and an unmatched document gets an empty array rather than being dropped.
See also: equality and pipeline lookup · lookup performance implications

