Read
Learn how to read documents from MongoDB using find, findOne, filtering, projection, sorting, and limiting results.
Read
The second operation in CRUD is Read — fetching documents from a collection. MongoDB gives you two methods for this:
findOne()— fetch a single documentfind()— fetch multiple documents
These two methods are the foundation of every query you will ever write in MongoDB.
findOne
findOne() returns the first document that matches your filter. If no document matches, it returns null.
Syntax
db.collection.findOne(filter)Example — Find one student by name
db.students.findOne({ name: "Ali Hassan" })Result
{
_id: ObjectId("64a1f2c3e4b0a1b2c3d4e5f6"),
name: "Ali Hassan",
age: 16,
grade: "10th",
subjects: ["Math", "Physics", "English"],
enrolled: true,
enrollmentDate: ISODate("2024-09-01T00:00:00.000Z"),
address: { city: "Lahore", country: "Pakistan" }
}Find by _id
The most common use of findOne() is finding a document by its _id:
const { ObjectId } = require('mongodb');
db.students.findOne({
_id: new ObjectId("64a1f2c3e4b0a1b2c3d4e5f6")
})Always wrap the _id string in new ObjectId(). Passing a plain string will not find anything because a string and an ObjectId are different types in MongoDB.
find
find() returns all documents that match your filter. If you pass no filter, it returns every document in the collection.
Syntax
db.collection.find(filter)Example — Find all students
db.students.find()Example — Find all 10th grade students
db.students.find({ grade: "10th" })Result
[
{
_id: ObjectId("64a1f2c3e4b0a1b2c3d4e5f6"),
name: "Ali Hassan",
age: 16,
grade: "10th",
subjects: ["Math", "Physics", "English"],
enrolled: true
},
{
_id: ObjectId("64a1f2c3e4b0a1b2c3d4e5f9"),
name: "Bilal Ahmed",
age: 16,
grade: "10th",
subjects: ["Physics", "Math", "Urdu"],
enrolled: false
}
]Example — Find all enrolled students
db.students.find({ enrolled: true })Example — Find by multiple fields
When you pass multiple fields in the filter, MongoDB returns only documents that match all of them:
// Students in 10th grade AND enrolled
db.students.find({
grade: "10th",
enrolled: true
})Filtering Nested Fields
To filter by a field inside an embedded document, use dot notation:
// Find students from Lahore
db.students.find({ "address.city": "Lahore" })Always wrap the dot notation path in quotes.
Filtering Array Fields
To find documents where an array contains a specific value, just use the value directly in the filter:
// Find students who take Math
db.students.find({ subjects: "Math" })MongoDB checks if "Math" exists anywhere in the subjects array. You do not need any special operator for this.
Projection
By default, find() returns every field in each document. Projection lets you choose which fields to include or exclude.
Syntax
db.collection.find(filter, projection)Include specific fields
Pass 1 for fields you want to include. The _id is always included unless you explicitly exclude it:
// Return only name and grade
db.students.find(
{ grade: "10th" },
{ name: 1, grade: 1 }
)Result
[
{ _id: ObjectId("..."), name: "Ali Hassan", grade: "10th" },
{ _id: ObjectId("..."), name: "Bilal Ahmed", grade: "10th" }
]Exclude specific fields
Pass 0 for fields you want to exclude:
// Return everything except address and enrollmentDate
db.students.find(
{ grade: "10th" },
{ address: 0, enrollmentDate: 0 }
)Exclude _id
// Return only name and grade, no _id
db.students.find(
{ grade: "10th" },
{ name: 1, grade: 1, _id: 0 }
)You cannot mix include and exclude in the same projection — for example { name: 1, age: 0 } is not allowed. The only exception is _id — you can always explicitly set _id: 0 even when including other fields.
Sorting Results
Use .sort() to control the order of results. Pass 1 for ascending and -1 for descending:
// Sort students by age — youngest first
db.students.find().sort({ age: 1 })
// Sort students by age — oldest first
db.students.find().sort({ age: -1 })
// Sort by grade ascending, then by name ascending
db.students.find().sort({ grade: 1, name: 1 })Limiting Results
Use .limit() to control how many documents are returned:
// Return only 3 students
db.students.find().limit(3)Skipping Results
Use .skip() to skip a number of documents — useful for pagination:
// Skip the first 5 students, return the next 5
db.students.find().skip(5).limit(5)Chaining sort, limit, and skip
You can chain these methods together:
// Get the top 3 oldest students in 10th grade
db.students
.find({ grade: "10th" })
.sort({ age: -1 })
.limit(3)// Page 2 of students — 5 per page, sorted by name
db.students
.find({ enrolled: true })
.sort({ name: 1 })
.skip(5)
.limit(5)MongoDB always applies sort first, then skip, then limit — regardless of the order you chain them in your code. So .find().limit(5).skip(2).sort({ age: 1 }) gives the same result as .find().sort({ age: 1 }).skip(2).limit(5).
Counting Documents
To count how many documents match a filter, use countDocuments():
// How many students are enrolled?
db.students.countDocuments({ enrolled: true })// How many students are in 10th grade?
db.students.countDocuments({ grade: "10th" })In Node.js
In a Node.js app, find() returns a cursor — not an array directly. Call .toArray() to get all results as an array:
const db = client.db('school');
const students = db.collection('students');
// findOne — returns a single document directly
const student = await students.findOne({ name: "Ali Hassan" });
console.log(student);
// find — returns a cursor, call toArray() to get results
const tenthGrade = await students
.find({ grade: "10th" })
.sort({ name: 1 })
.limit(10)
.toArray();
console.log(tenthGrade);
// countDocuments
const enrolledCount = await students.countDocuments({ enrolled: true });
console.log(`Enrolled students: ${enrolledCount}`);School System Queries
Here are some useful queries for our school system that combine everything we covered:
// All enrolled students, sorted by name, showing only name and grade
db.students.find(
{ enrolled: true },
{ name: 1, grade: 1, _id: 0 }
).sort({ name: 1 })
// All students from Lahore in 10th grade
db.students.find({
grade: "10th",
"address.city": "Lahore"
})
// The 5 youngest students
db.students
.find({ enrolled: true })
.sort({ age: 1 })
.limit(5)
// Find one teacher who teaches Math
db.teachers.findOne({ subject: "Math" })
// All active teachers, showing only name and subject
db.teachers.find(
{ active: true },
{ name: 1, subject: 1, _id: 0 }
)findOne vs find
findOne | find | |
|---|---|---|
| Returns | One document or null | Cursor of all matching documents |
| Use when | You need one specific document | You need multiple documents |
| In Node.js | Returns document directly | Call .toArray() to get results |
| Speed | Stops after first match | Scans all matching documents |
Use findOne() whenever you know you only need one document — like finding by _id or by a unique field. It is faster than find() because MongoDB stops searching as soon as it finds the first match.