Aggregation and covered queriessenior8+ years

A hot endpoint runs `db.orders.find({"customer.id": id}, {_id: 0, "customer.id": 1, placedAt: 1, orderNumber: 1})` against an index on `{"customer.id": 1, placedAt: -1}`, expecting a covered query. `explain()` shows `totalDocsExamined` equal to the number of documents returned, not zero. Why isn't it covered, and what's the actual aggregation-pipeline cost of joining in the order's line items afterward?

A covered query needs every field in both the filter and the projection to be present in the index — no exceptions, not even one extra field. This projection asks for orderNumber, and orderNumber isn't a field in the {"customer.id": 1, placedAt: -1} index at all, so the plan falls back to a normal index scan plus a document fetch for every matching entry, which is exactly why totalDocsExamined isn't zero. As for joining in line items afterward with $lookup: it's a genuine join, with a join's cost, and the lesson's rule is to run it after any $limit that shrinks the stream first, on an indexed foreign field — doing it before a limit means paying the join's cost for every matching order instead of just the ones actually returned.

The lesson behind it →