What is the difference between a covered query and a normal query in MongoDB?
Understand covered queries in MongoDB: how they answer from the index without fetching documents, the _id and projection rules, and how to verify with explain.
Expected Interview Answer
A covered query is one that MongoDB can answer entirely from an index, without fetching the actual documents, because every field in the filter and projection is present in the index. A normal query, by contrast, uses the index only to locate matching documents and then reads each one from the collection to return the requested fields.
For a query to be covered, all fields referenced in the query and projection must be part of a single index, and the _id field must be explicitly excluded unless it is in the index. Covered queries show a totalDocsExamined of 0 in explain output because no document fetch occurs, making them very fast. Normal queries incur an extra FETCH stage that reads documents from disk or cache, which is slower and drives more I/O.
- Answers served from the index with zero document fetches
- totalDocsExamined is 0, reducing disk and cache I/O
- Lower latency for read-heavy, high-throughput endpoints
- Less working-set memory pressure
- Predictable performance for projection-limited APIs
AI Mentor Explanation
Covered query is like reading the scoreboard on the stadium wall: runs, wickets, and overs are all printed there, so you never walk down to the pitch to ask the umpire. A normal query is when the scoreboard only lists player IDs, forcing you to trek to the dressing room to look up each name — the index pointed you there, but you still fetched the full details separately.
Step-by-Step Explanation
Step 1
Identify the query and projection fields
List every field used in the filter and every field returned by the projection.
Step 2
Build one covering index
Create a compound index that contains all those fields, e.g. { status: 1, email: 1 }.
Step 3
Project only indexed fields
Return exactly the indexed fields and no others; extra fields force a document fetch.
Step 4
Exclude _id when needed
Add _id: 0 to the projection unless _id is part of the index, since _id is returned by default.
Step 5
Verify coverage with explain
Run explain('executionStats') and confirm totalDocsExamined is 0 and the plan has an IXSCAN with no FETCH stage.
What Interviewer Expects
- Precise definition: answered entirely from the index, no document fetch
- The two conditions: all fields in the index, _id handled correctly
- Recognizing totalDocsExamined = 0 in explain output
- Awareness that projection choices affect coverage
- Understanding the performance benefit versus a FETCH stage
Common Mistakes
- Forgetting to exclude _id, which breaks coverage
- Projecting a field that is not in the index
- Believing any indexed query is automatically covered
- Confusing 'index used' (IXSCAN) with 'query covered' (no FETCH)
- Not checking totalDocsExamined to confirm coverage
Best Answer (HR Friendly)
“A covered query answers a request using only the index, like reading everything you need off a labeled sign without going inside the building. A normal query uses the index just to find the right documents and then opens each one, which is a bit slower because of the extra step.”
Code Example
// Index containing all fields the query touches
db.users.createIndex({ status: 1, email: 1 })
// COVERED: filter and projection use only indexed fields, and _id is excluded
db.users.find(
{ status: 'active' },
{ _id: 0, status: 1, email: 1 }
)
// explain('executionStats') -> totalDocsExamined: 0, no FETCH stage
// NORMAL: 'name' is not in the index, so MongoDB must fetch documents
db.users.find(
{ status: 'active' },
{ _id: 0, status: 1, email: 1, name: 1 }
)
// explain -> IXSCAN followed by a FETCH stage, totalDocsExamined > 0Follow-up Questions
- Why does forgetting _id: 0 prevent a query from being covered?
- How do you confirm a query is covered using explain output?
- Can a query with a range filter still be covered?
- What is the difference between IXSCAN and FETCH stages?
- When is chasing a covered query not worth the extra index cost?
MCQ Practice
1. Which condition is required for a query to be covered in MongoDB?
Coverage requires every referenced field (filter and projection) to exist in one index, and _id must be excluded unless indexed, so no document fetch is needed.
2. In explain('executionStats'), what signals a covered query?
A covered query examines no documents, so totalDocsExamined is 0 and the plan has an IXSCAN with no following FETCH stage.
3. Why might a query that uses an index still NOT be covered?
If a returned field is not in the index, MongoDB must fetch the document to read it, adding a FETCH stage and breaking coverage.
Flash Cards
What is a covered query? — A query answered entirely from an index, with no document fetch, because all filter and projection fields are indexed.
How is a normal query different? — It uses the index to find matches, then fetches each document to read the requested fields (a FETCH stage).
Why exclude _id in a covered query? — _id is returned by default; unless it's in the index, including it forces a document fetch and breaks coverage.
How do you confirm coverage? — explain('executionStats') shows totalDocsExamined: 0 and an IXSCAN with no FETCH stage.
Main benefit of a covered query? — Lower latency and I/O because no documents are read from disk or cache.