MongoDB Projection and Sorting

When retrieving documents from MongoDB, there are two important controls available: projection and sorting. Projection decides which fields appear in the result, and sorting determines the order in which the results are returned. Together, they make queries more efficient and results more readable.

What is Projection?

By default, when a query runs, MongoDB returns the entire document — every field it contains. Projection allows choosing only specific fields to include or exclude from the result. This reduces the amount of data sent over the network and keeps results focused on what is actually needed.

Projection is passed as the second argument to the find() method.

db.collection.find( <filter>, <projection> )

All examples use this employees collection:

db.employees.insertMany([
  { name: "Amit Sharma", age: 30, department: "IT", salary: 75000, city: "Delhi" },
  { name: "Nisha Patel", age: 27, department: "HR", salary: 55000, city: "Mumbai" },
  { name: "Rohit Verma", age: 35, department: "IT", salary: 90000, city: "Pune" },
  { name: "Kavita Joshi", age: 29, department: "Finance", salary: 62000, city: "Delhi" },
  { name: "Suresh Iyer", age: 40, department: "IT", salary: 1200000, city: "Chennai" }
])

Including Specific Fields — Value 1

Set a field to 1 in the projection to include it in the result. Only those fields appear, along with _id which is always included by default.

db.employees.find({}, { name: 1, department: 1 })

Result:

{ "_id": ObjectId("..."), "name": "Amit Sharma", "department": "IT" }
{ "_id": ObjectId("..."), "name": "Nisha Patel", "department": "HR" }
...

The empty filter {} means all documents are returned. Only name and department appear in each result, along with the default _id.

Excluding the _id Field

To remove _id from results, set it to 0 explicitly:

db.employees.find({}, { name: 1, department: 1, _id: 0 })

Result:

{ "name": "Amit Sharma", "department": "IT" }
{ "name": "Nisha Patel", "department": "HR" }
...

Now the results are cleaner without the system-generated ID.

Excluding Specific Fields — Value 0

Set a field to 0 to exclude it from the result. All other fields will appear.

db.employees.find({}, { salary: 0, city: 0 })

Result:

{ "_id": ObjectId("..."), "name": "Amit Sharma", "age": 30, "department": "IT" }

This is useful when most fields are needed but only a few should be hidden — like hiding sensitive data such as salary.

Important Rule

Inclusion and exclusion cannot be mixed in a single projection (except for _id). Setting some fields to 1 and others to 0 in the same query is not allowed. Only one mode at a time.

// This works — inclusion with _id exclusion
db.employees.find({}, { name: 1, department: 1, _id: 0 })

// This does NOT work — mixing inclusion and exclusion
db.employees.find({}, { name: 1, salary: 0 })  // Error

Projection on Nested Fields

To project a field inside an embedded document, use dot notation.

db.employees.find({}, { "address.city": 1, name: 1, _id: 0 })

This returns only the name and the city inside the address sub-document.

What is Sorting?

Sorting controls the order in which documents appear in the results. The sort() method is chained after find().

db.collection.find().sort( <sort specification> )

The sort specification uses 1 for ascending order (A → Z, smallest → largest) and -1 for descending order (Z → A, largest → smallest).

Ascending Sort — Lowest to Highest

db.employees.find().sort({ salary: 1 })

Results appear with the lowest salary first and highest salary last.

Descending Sort — Highest to Lowest

db.employees.find().sort({ salary: -1 })

Results appear with the highest salary first. This is useful for leaderboards, top products, or recent records.

Alphabetical Sort on Strings

db.employees.find().sort({ name: 1 })

Sorts employee names alphabetically from A to Z.

Sorting by Multiple Fields

db.employees.find().sort({ department: 1, salary: -1 })

First, results are sorted alphabetically by department. Within the same department, employees with the highest salary appear first. This is called a compound sort.

Combining Filter, Projection, and Sort

All three can be used together in a single query.

db.employees.find(
  { department: "IT" },
  { name: 1, salary: 1, _id: 0 }
).sort({ salary: -1 })

This returns only IT employees, shows only their name and salary, and lists them from highest to lowest salary.

Result:

{ "name": "Suresh Iyer", "salary": 1200000 }
{ "name": "Rohit Verma", "salary": 90000 }
{ "name": "Amit Sharma", "salary": 75000 }

Limiting Results with limit()

The limit() method restricts the number of documents returned. It is often paired with sort() to get the top N results.

db.employees.find().sort({ salary: -1 }).limit(3)

This returns the top 3 highest-paid employees.

Skipping Results with skip()

The skip() method skips a given number of documents before returning results. This is commonly used for pagination.

db.employees.find().sort({ name: 1 }).skip(2).limit(2)

This skips the first 2 records and returns the next 2 — useful for implementing page 2 of a results list.

Pagination Formula

// Page 1: skip(0).limit(5)
// Page 2: skip(5).limit(5)
// Page 3: skip(10).limit(5)

The formula is: skip = (pageNumber - 1) * pageSize

Method Chaining Order

When chaining multiple methods together, the order matters for readability but MongoDB processes them internally in the most efficient way:

db.employees
  .find({ department: "IT" }, { name: 1, salary: 1, _id: 0 })
  .sort({ salary: -1 })
  .skip(0)
  .limit(5)

Summary

Projection controls which fields appear in query results by setting field values to 1 (include) or 0 (exclude). Mixing inclusions and exclusions in the same projection is not allowed, except for _id. Sorting uses sort() with 1 for ascending and -1 for descending order. Multiple fields can be sorted in one query. The limit() method caps the number of results, and skip() enables pagination. Using these methods together produces clean, targeted, and efficient query results.

Leave a Comment