MongoDB Projection
In MongoDB, when you query a collection, by default, all fields of the documents matching your query criteria are returned. However, in many real-world scenarios, you may only need specific fields from these documents. This is where projection comes in - a powerful feature that allows you to control which fields are returned in query results.
What is Projection?
Projection in MongoDB is like using a filter on your query results. It lets you specify which fields to include or exclude from the returned documents, thereby:
- Reducing network overhead by transferring less data
- Decreasing memory usage in your application
- Improving overall performance of your application
- Making your code more maintainable by focusing on relevant data
Basic Syntax
Projection is specified as the second parameter in the find()
method:
db.collection.find(query, projection)
Where:
query
: The selection criteria for the query (first parameter)projection
: The specification of fields to include or exclude (second parameter)
Including Fields
To include specific fields, set their value to 1
in the projection document:
db.users.find({}, { name: 1, email: 1 })
This query will return only the name
and email
fields, along with the _id
field (which is included by default).
Example Input and Output
Input:
// Sample collection data
db.users.insertMany([
{ name: "Alice", email: "[email protected]", age: 28, city: "New York" },
{ name: "Bob", email: "[email protected]", age: 34, city: "Boston" }
])
// Query with projection
db.users.find({}, { name: 1, email: 1 })
Output:
[
{ "_id": ObjectId("..."), "name": "Alice", "email": "[email protected]" },
{ "_id": ObjectId("..."), "name": "Bob", "email": "[email protected]" }
]
Excluding Fields
To exclude specific fields, set their value to 0
in the projection document:
db.users.find({}, { age: 0, city: 0 })
This query will return all fields except for age
and city
.
Example Input and Output
Input:
// Query with exclusion projection
db.users.find({}, { age: 0, city: 0 })
Output:
[
{ "_id": ObjectId("..."), "name": "Alice", "email": "[email protected]" },
{ "_id": ObjectId("..."), "name": "Bob", "email": "[email protected]" }
]
Excluding the _id Field
The _id
field is included by default when using projection. To exclude it, you must explicitly set it to 0
:
db.users.find({}, { name: 1, email: 1, _id: 0 })
Example Input and Output
Input:
db.users.find({}, { name: 1, email: 1, _id: 0 })
Output:
[
{ "name": "Alice", "email": "[email protected]" },
{ "name": "Bob", "email": "[email protected]" }
]
Important Rules
- You cannot mix inclusion and exclusion in the same projection document, except for the
_id
field. This means you can't do:
// This will cause an error
db.users.find({}, { name: 1, age: 0 })
- In inclusion mode (using
1
), only the specified fields plus_id
are returned. - In exclusion mode (using
0
), all fields except the specified ones are returned.
Projection in Nested Documents
MongoDB projection also works with nested documents and arrays. To access nested fields, use dot notation:
db.students.find({}, { "name": 1, "grades.math": 1 })
Example with Nested Documents
Input:
// Sample nested document
db.students.insertMany([
{
name: "Alice",
grades: {
math: 90,
science: 85,
history: 78
},
hobbies: ["reading", "swimming"]
},
{
name: "Bob",
grades: {
math: 76,
science: 92,
history: 88
},
hobbies: ["gaming", "basketball"]
}
])
// Query with projection on nested fields
db.students.find({}, { name: 1, "grades.math": 1 })
Output:
[
{ "_id": ObjectId("..."), "name": "Alice", "grades": { "math": 90 } },
{ "_id": ObjectId("..."), "name": "Bob", "grades": { "math": 76 } }
]
Projection in Arrays: The $slice Operator
For array fields, you can use the $slice
operator to control how many elements are returned:
db.students.find({}, { name: 1, hobbies: { $slice: 1 } })
This returns only the first element of the hobbies
array for each document.
Example Using $slice
Input:
// Query to get only the first hobby
db.students.find({}, { name: 1, hobbies: { $slice: 1 } })
Output:
[
{ "_id": ObjectId("..."), "name": "Alice", "hobbies": ["reading"] },
{ "_id": ObjectId("..."), "name": "Bob", "hobbies": ["gaming"] }
]
You can also specify a range with $slice
:
// Get 2 elements starting from position 1 (zero-based index)
db.students.find({}, { name: 1, hobbies: { $slice: [1, 2] } })
Projection with Aggregation Framework
For more advanced projections, MongoDB offers the Aggregation Framework with the $project
stage:
db.users.aggregate([
{ $match: { age: { $gt: 25 } } },
{ $project: {
name: 1,
email: 1,
isAdult: { $gte: ["$age", 18] }
}}
])
This query not only projects name
and email
fields but also creates a new computed field isAdult
that evaluates to a boolean.
Example with Aggregation
Input:
db.users.aggregate([
{ $project: {
name: 1,
firstInitial: { $substr: ["$name", 0, 1] },
emailDomain: { $arrayElemAt: [{ $split: ["$email", "@"] }, 1] }
}}
])
Output:
[
{ "_id": ObjectId("..."), "name": "Alice", "firstInitial": "A", "emailDomain": "example.com" },
{ "_id": ObjectId("..."), "name": "Bob", "firstInitial": "B", "emailDomain": "example.com" }
]
Real-World Example: User Dashboard
Let's create a more realistic example of how projection can be used in a web application user dashboard:
// Query to retrieve only necessary user information for a dashboard
db.users.find(
{ active: true },
{
name: 1,
email: 1,
profileImage: 1,
lastLogin: 1,
notifications: { $slice: -5 }, // Only the 5 most recent notifications
_id: 0
}
)
This query:
- Filters for active users
- Returns only the fields needed for the dashboard
- Limits notifications to just the 5 most recent ones
- Excludes the _id field to reduce data size
Performance Benefits
Projection can significantly improve performance, especially when:
- Documents are large - Retrieving fewer fields means less data transfer
- Reading over a network - Reduces latency when MongoDB is hosted remotely
- Working with high-volume collections - Memory usage is optimized
When to Use Projection
- DO use projection whenever you don't need all fields in a document
- DO use it when working with large documents to optimize performance
- DO use it when creating APIs where clients might need specific fields
- DON'T use mixed inclusion and exclusion (except with _id)
- CONSIDER the aggregation framework for more complex transformations
Summary
MongoDB projection is a powerful feature that allows you to:
- Selectively include or exclude fields from query results
- Reduce network bandwidth and memory usage
- Work efficiently with nested documents and arrays
- Create more focused and efficient queries
By mastering projection, you can make your MongoDB applications more efficient and responsive, especially when dealing with large documents or high-volume collections.
Exercises
- Write a query that returns only the title and publication year of all books in a collection.
- Create a projection that returns user documents without sensitive information like passwords and personal identification.
- Use the
$slice
operator to return only the 3 most recent comments from a blog post document. - Write an aggregation query that projects user names in all uppercase and calculates their membership duration in days.
Additional Resources
💡 Found a typo or mistake? Click "Edit this page" to suggest a correction. Your feedback is greatly appreciated!