Projection
Projection controls which fields are returned in query results. By default, find() returns all fields. Projection lets you include only the fields you need — reducing network transfer and improving performance.
Inclusion Projection
Set fields to 1 to include them. Only those fields are returned (plus _id by default).
Inclusion projection
// Return only 'name' and 'email' fields (plus _id)
db.users.find({}, { name: 1, email: 1 })
// Result shape:
// { _id: ObjectId('...'), name: 'Alice', email: 'alice@example.com' }
// With a filter
db.users.find({ active: true }, { name: 1, email: 1 })Exclusion Projection
Set fields to 0 to exclude them. All other fields are returned.
Exclusion projection
// Return everything EXCEPT 'password' and '__v'
db.users.find({}, { password: 0, __v: 0 })
// Result shape:
// { _id: ObjectId('...'), name: 'Alice', email: 'alice@example.com', createdAt: ... }
// With a filter
db.users.find({ active: true }, { password: 0, refreshToken: 0 })Excluding _id
Remove _id from results
// Include name and email, but suppress _id
db.users.find({}, { _id: 0, name: 1, email: 1 })
// Result shape:
// { name: 'Alice', email: 'alice@example.com' }
// No _id field at all_id). Doing so throws a MongoDB error.Projecting Nested Fields
Nested field projection
// Return only specific nested fields using dot notation
db.users.find(
{},
{ 'address.city': 1, 'address.zip': 1 }
)
// Result shape:
// { _id: ObjectId('...'), address: { city: 'New York', zip: '10001' } }
// Other address fields (street, country) are excluded
// Works for deeply nested fields too
db.orders.find(
{},
{ 'shipping.address.city': 1, 'shipping.carrier': 1 }
)$slice — Limit Array Elements
$slice limits the number of elements returned from an array field.
$slice projection
// Return FIRST 3 tags
db.posts.find({}, { tags: { $slice: 3 } })
// Return LAST 2 comments
db.posts.find({}, { comments: { $slice: -2 } })
// Skip 5 elements, then return the next 3 [skip, limit]
db.posts.find({}, { comments: { $slice: [5, 3] } })$elemMatch Projection — First Matching Array Element
$elemMatch in projection
// Return only the FIRST order item where price > 100
db.orders.find(
{ 'items.price': { $gt: 100 } },
{ items: { $elemMatch: { price: { $gt: 100 } } } }
)
// Result shape:
// { _id: ObjectId('...'), items: [{ product: 'Laptop', price: 999 }] }
// Only the first matching item is returned, not all itemsThe Positional $ in Projection
Positional projection
// The $ in projection returns ONLY the matched array element from the query
db.students.find(
{ grades: { $elemMatch: { subject: 'Math', score: { $gt: 90 } } } },
{ 'grades.$': 1 }
)
// The query must reference the same array field used in the $ projection
// Result: only the first element that matched the query condition is returnedProjection in Practice — Performance Impact
Always project only the fields you need in production. Fetching full documents when you only need 2 fields wastes network bandwidth and memory.
Scenario | Without Projection | With Projection |
|---|---|---|
1,000 users, full doc (5 KB each) | 5 MB | 50 KB (name + email only) |
10,000 orders full | 50 MB | 500 KB (id + total only) |