Skip to content

MongoDB - Projection

In MongoDB, projection is the mechanism for selecting only the necessary fields from a document, rather than retrieving the entire document. This is a critical practice for optimizing performance, especially by reducing network traffic and memory usage on the client side.

The find() method supports a projection document to specify which fields to return. You can pass it as a second argument to find() or, more commonly in modern drivers and shells, by chaining the .project() method.

The rule is simple: use 1 to include a field and 0 to exclude a field. By default, the _id field is always included unless explicitly excluded.

// Modern preferred syntax using .project()
db.COLLECTION_NAME.find({/* query */}).project({/* projection */});
// Traditional syntax
db.COLLECTION_NAME.find({/* query */}, {/* projection */});

Consider a users collection with detailed user profiles:

{
"_id": ObjectId("..."),
"username": "alex_doe",
"email": "alex.doe@example.com",
"profile": {
"firstName": "Alex",
"lastName": "Doe",
"dob": ISODate("1990-05-15T00:00:00Z")
},
"loginHistory": [ /* ... large array ... */ ]
}

If we only need to display a list of usernames and emails, retrieving the large loginHistory array would be wasteful. We can use projection to fetch only what’s needed.

// Include only username and email, and exclude _id
db.users.find({}).project({ username: 1, email: 1, _id: 0 });

The result would look like this, containing only the projected fields:

{
"username": "alex_doe",
"email": "alex.doe@example.com"
}

You can use dot notation to project fields within embedded documents.

// Get the username and just the first name from the profile
db.users.find({}).project({
username: 1,
"profile.firstName": 1,
_id: 0
});

Result:

{
"username": "alex_doe",
"profile": {
"firstName": "Alex"
}
}
  • Inclusion vs. Exclusion: You cannot mix inclusion (1) and exclusion (0) specifiers in the same projection, with one exception: you can always explicitly exclude the _id field (_id: 0) in an inclusion projection.
  • _id Field: The _id field is always returned by default. It’s the only field you can explicitly exclude when using an inclusion projection.
  • Performance Boost: Always project only the fields your application needs. This minimizes data transfer over the network and reduces the processing load on your application.
  • Covered Queries: Projection is the key to creating ‘covered queries’. When a query’s filter and projection can be satisfied entirely by an index, MongoDB doesn’t need to read the documents from disk, leading to a massive performance improvement. For a query to be covered, all fields in the projection must be part of the index.

A common mistake is trying to mix inclusion and exclusion.

// THIS WILL CAUSE AN ERROR
db.users.find({}).project({ username: 1, loginHistory: 0 });
// Error message:
// "Projection cannot have a mix of inclusion and exclusion"

To achieve this, you must either include all fields except loginHistory or exclude loginHistory (which will return all other fields).