The statement isn’t executed when using EXPLAIN, only the parsing and planning stages take place.
DQL
DQL
Join plans
When aSELECT statement uses one or more JOIN terms, each join appears in the plan as an nlJoin (nested-loop join) operator. Read the plan from top to bottom: the outer (driving) collection is scanned or probed first, then for each outer row the nlJoin operator evaluates its inner sub-plan to find matching documents in the joined collection.
The nlJoin operator
DQL
- Dynamic span bounds. The index scan span on the inner collection references the outer alias —
"expr": "c.cust_id"— meaning the span is re-evaluated for every outer row. This is how the nested-loop join drives the inner index lookup. fetchstep. When the query projects fields not stored in the index, afetchoperator retrieves the full document after the index scan. If all projected fields are covered by the index, thefetchstep is absent entirely (see Covering index scans below).
LEFT OUTER JOIN
ALEFT OUTER JOIN produces the same plan shape as INNER JOIN with the addition of "outer": true on the nlJoin operator, which instructs the engine to emit a padded row (inner fields set to MISSING) when the inner collection has no match:
RIGHT OUTER JOIN (rewritten)
ARIGHT OUTER JOIN is silently rewritten so that the originally-right collection becomes the outer (driving) leg. The plan therefore shows the right-hand collection scanned first, with the left-hand collection as the nlJoin inner leg and "outer": true set on the operator:
DQL
orders (o) is the outer leg and customers (c) is the inner leg, looked up via an index on cust_id.
Multi-collection plans
A three-collection join produces two sequentialnlJoin operators. The second operator’s condition may reference aliases introduced by the first join:
JOIN term appends a further nlJoin to the sequence.
Covering index scans in joins
When the query projects only fields stored in the inner collection’s index (plus_id, which is always available), the planner uses a covering index scan and omits the fetch step entirely, reducing document reads significantly. The index scan descriptor includes "covering": true:
DQL
DQL
Intersect scans on join inner legs
When theON condition or WHERE clause provides multiple filterable predicates against the inner collection, the planner may combine several index scans into an intersectScan before the fetch — exactly as for non-join queries. The intersectScan appears inside the nlJoin’s inner sequence:
DQL
ID-based joins
When theON condition equates an outer field to _id of the inner collection, the planner uses an idScan — a direct document lookup by ID — rather than a secondary index scan. No index on the inner collection is required: