Skip to main content

MongoDB find(): A Complete Beginner's Guide to Querying Data

This guide explains how to use the MongoDB find() method to query, filter, sort, and paginate data with real-world examples. Perfect for beginners and those transitioning from SQL.
Jun 12, 2025  · 9 min read

MongoDB is a popular NoSQL database designed for flexibility and performance. Unlike traditional relational databases that use structured tables and SQL, MongoDB stores data in flexible, JSON-like documents. This makes it ideal for developers working with dynamic or semi-structured data.

One of the most important operations you’ll perform in MongoDB is querying data, and the most commonly used method to do this is find(). Whether you’re just getting started or looking to improve your query skills, understanding how find() works is essential for navigating and manipulating your MongoDB data effectively.

Imagine you’re exploring a movie database. You want to find all science fiction films released after the year 2000, or perhaps list all user comments made in a specific time frame. That’s where find() shines.

In this article, you’ll learn how to use the find() method to retrieve documents from a collection, apply filters, project fields, sort results, and optimize performance—all while working with the sample_mflix dataset.

For a hands-on walkthrough of using MongoDB in data science workflows, check out the Introduction to MongoDB in Python course.

Introduction to find() in MongoDB

The find() method is MongoDB’s primary way to retrieve documents from a collection. It returns a cursor to the documents that match the specified query. You can then iterate over this cursor, or convert it to an array, depending on your application’s needs.

Here is the full syntax:

db.collection.find(<query>, <projection>, <options>)

Parameters

  • query (optional): A document that defines the criteria for selecting documents. If you omit this parameter or pass an empty document ({}), find() will return all documents in the collection.
  • projection (optional): A document that specifies which fields to return. You can include (1) or exclude (0) fields. By default, MongoDB returns all fields, including _id.
  • options (optional): An additional document to configure query behavior. You can set things like sort order, pagination limits, timeouts, and index hints.

Example

To make the concepts as clear and applicable as possible, we’ll use the MongoDB Atlas sample dataset—specifically, the sample_mflix database. This dataset includes collections such as movies, comments, users, and theaters, which we’ll reference throughout the article to demonstrate each example.

db.books.find(
  { year: { $gte: 2000 } },              // query: books published in or after 2000
  { title: 1, author: 1, _id: 0 },        // projection: include only title and author
  { sort: { title: 1 }, limit: 5 }       // options: sort by title, return only 5 books
)

This query:

  • Filters books published in the year 2000 or later.
  • Returns only the title and author fields (excludes _id).
  • Sorts the results alphabetically by title (A-Z).
  • Limits the output to the first five matching books.

This query finds movies released after 2000, sorted by title and limited to five results.

Figure 1. This query finds movies released after 2000, sorted by title and limited to five results.

The result is a cursor, which lazily loads matching documents as you iterate over them. You can use .toArray() or .forEach() to process the results.

If you’re connected through the MongoDB shell (mongosh) and don’t assign the result to a variable, only the first 20 documents will display by default. To view additional documents, type it and press Enter. This process will continue fetching the next batch from the cursor.

> Note: The above is a shell-specific behavior, not a MongoDB limitation. In most MongoDB drivers (e.g., Node.js, Python, Java), calling .toArray() or iterating over the cursor automatically fetches all matching results. Cursor behavior may vary depending on the environment and language you’re using.

This query retrieves all movies, returning only the _id field and using the cursor to fetch additional results.

Figure 2. This query retrieves all movies, returning only the _id field and using the cursor to fetch additional results.

If you’re new to NoSQL databases, the Introduction to NoSQL course offers foundational concepts that complement this tutorial.

Writing Your First Queries

Continuing with the movie example, let’s say you want to fetch all movies in the Sci-Fi genre. Here’s how you’d do that:

db.movies.find({ genres: "Sci-Fi" })

Now, you want only movies released in or after the year 2000:

db.movies.find({ year: { $gte: 2000 } })

And if you want both? Combine conditions:

db.movies.find({ genres: "Sci-Fi", year: { $gte: 2000 } })

Alternatively, you can write it explicitly using $and:

db.movies.find({ $and: [ { genres: "Sci-Fi" }, { year: { $gte: 2000 } } ] })

Both queries return the same result—documents with the genre Sci-Fi and the release year 2000 or later. The first form is more concise and preferred when the fields are different.

These are different ways to write the query that produce the same result.

Figure 3. These are different ways to write the query that produce the same result.

Use find() like a filter funnel—each condition narrows down your results.

Using Comparison and Logical Operators

Now, let’s review how to use comparison and logical operators to take your queries to the next level.

Comparison operators

  • $eq, $ne: equal, not equal
  • $gt, $gte, $lt, $lte: greater/less than (or equal)
  • $in, $nin: in or not in array

Imagine you're tracking customer orders and want orders between $100 and $500:

db.orders.find({ total: { $gte: 100, $lte: 500 } })

Logical operators

  • $and, $or, $nor, $not

Now, imagine you want to show products in the "Books" category or priced under $20. Here’s an example query:

db.products.find({ $or: [ { category: "Books" }, { price: { $lt: 20 } } ] })

Querying nested fields

You can access nested fields using dot notation:

db.customers.find({ "address.city": "Chicago" })

Projecting Fields

Projection allows you to return only what you need, which can significantly improve performance and clarity.

db.movies.find({}, { directors: 1, languages: 1, _id: 0 })

Important: When specifying a projection, MongoDB requires you to choose between two modes: Either include specific fields (1) or exclude specific fields (0). You cannot mix both styles in the same projection, except for the _id field, which can be excluded even when other fields are included.

✅ Valid (inclusion only):

db.movies.find({}, { directors: 1, languages: 1 })

✅ Valid (exclusion only):

db.movies.find({}, { directors: 0, _id: 0 })

❌ Invalid (mix of inclusion and exclusion):

db.movies.find({}, { directors: 1, languages: 0 }) // Not allowed

The only exception is the _id field, which you can exclude even when including other fields:

db.movies.find({}, { directors: 1, _id: 0 }) // Allowed

This example demonstrates the error triggered by mixing field inclusion and exclusion in a single projection, which MongoDB does not allow, except for _id.

Figure 4. This example demonstrates the error triggered by mixing field inclusion and exclusion in a single projection, which MongoDB does not allow, except for `_id`.

Sorting, Limiting, and Skipping Results

When working with large datasets, showing users only a portion of the data at a time is common—a technique known as pagination. For example, a streaming app might show 10 movies per page instead of loading thousands at once. This not only improves performance but also enhances the user experience.

In MongoDB, pagination is achieved using a combination of sort(), limit(), and skip().

SQL vs. MongoDB: Basic comparison

If you’re coming from an SQL background, here’s how common pagination concepts compare:

Basic query in SQL: 

SELECT * FROM movies WHERE year >= 2000

The same can be expressed in MongoDB as follows:

db.movies.find({ year: { $gte: 2000 } })

Field selection in SQL: 

SELECT title, year FROM movies

Field selection in MongoDB: 

db.movies.find({}, { title: 1, year: 1, _id: 0 })

Now, let’s look at a few more examples of common query operations:

Sorting:

  • SQL: ORDER BY title ASC
  • MongoDB: .sort({ title: 1 })

Limiting:

  • SQL: LIMIT 10
  • MongoDB: .limit(10)

Skipping:

  • SQL: OFFSET 10
  • MongoDB: .skip(10)

Understanding these parallels can help SQL users transition more easily to MongoDB’s document-based query system.

Sorting results

Sorting helps you organize your results based on a specific field—for instance, to sort movies by title in alphabetical order:

db.movies.find().sort({ title: 1 }) // ascending (A–Z)
  • 1 means ascending order (A-Z, 0-9)
  • -1 means descending order (Z-A, 9-0)

Limiting results

Return only a certain number of results—for example, the first 10:

db.movies.find().limit(10)

This is useful when implementing “Top 10” lists or initial views.

Skipping results

Use this to skip documents. It’s often used with limit() for pagination:

db.movies.find().skip(10).limit(10)

This skips the first 10 documents and returns the next 10, effectively showing Page 2 when pageSize = 10.

Pagination formula:

skip = (pageNumber - 1) * pageSize

> Note: Using skip() for deep pagination (e.g., skip(10000)) can be inefficient, as MongoDB still scans and discards the skipped documents. For better performance with large datasets, consider range-based pagination using indexed fields like _id.

Combined example: Page 3, 10 movies per page, sorted by title

db.movies.find()
  .sort({ title: 1 })
  .skip(20)
  .limit(10)

This pattern is also helpful for features like “load more” or infinite scroll.

This query retrieves the third page of results (10 movies per page), ordered by title.

Figure 5. This query retrieves the third page of results (10 movies per page), ordered by title.

Working With Cursors

The find() method returns a cursor—a pointer to the result set. You can iterate over it:

const cursor = db.movies.find({ type: "movie" });
cursor.forEach(doc => print(doc.name));

Or convert it to an array:

const results = db.collection.find().toArray();

After calling find(), you receive a cursor. You can use it to iterate over documents or convert the full result set into an array.

Figure 6. After calling `find()`, you receive a cursor. You can use it to iterate over documents or convert the full result set into an array.

> Note: The cursor object is available in mongosh or code via drivers (e.g., Node.js, Python). GUI tools like MongoDB Compass handle cursors internally. You won’t access or iterate over them directly.

Advanced Cursor Options

To fine-tune your queries, you can use additional cursor methods:

db.users.find({ age: { $gte: 30 } })
  .sort({ name: 1 })
  .limit(10)
  .skip(5)
  .maxTimeMS(200)
  .hint({ age: 1 })
  • maxTimeMS(ms): aborts the query if it takes too long
  • hint(): forces MongoDB to use a specific index
  • batchSize(n): controls the number of docs per batch

Preparing for interviews? Explore the Top 25 MongoDB Interview Questions and Answers to test your understanding of core concepts like find().

Indexes and Performance Optimization

Indexes are like cheat sheets—they help MongoDB retrieve documents faster.

Creating an index

db.movies.createIndex({ type: 1 })

Using .explain()

db.users.find({ type: "movie" }).explain()

This reveals whether indexes are being used and how efficient your query is.

Without an index: Run explain() on the query before indexing.

Figure 7. Run `explain()` on the query before indexing.

Creating an index: 

Create a simple index on the type field.

Figure 8. Create a simple index on the type field.

With an index: 

Run the same query with explain(), now using an index.

Figure 9. Run the same query with `explain()`, now using an index.

You can see that the stage that was previously CollScan (scanning the collection) has become Fetch + IXSCAN, which is basically using the index + searching for other data that is not part of the index (since we are returning everything).

Using MongoDB Compass to Visualize Queries

If you prefer visual tools, MongoDB Compass is the official GUI client. It allows you to:

  • Visually build queries using filters.
  • Preview documents and indexes.
  • Optimize and validate query performance.

You can even switch to the "JSON view" to copy/paste queries into your code.

Using Atlas + AI to Generate Queries

If you're using MongoDB Atlas, you can leverage Atlas Search with the AI-powered query builder.

Just type a natural-language prompt like:

"Show me all customers from Brazil who placed orders over $100 in the last month."

Atlas suggests a matching MongoDB query using find() or $search. It’s an excellent productivity booster, especially when you're unsure of the syntax.

Use Compass to generate a query from natural language.

Figure 10. Use Compass to generate a query from natural language.

Common Pitfalls and How to Avoid Them

  • Querying unindexed fields → Leads to slow performance
  • Large result sets → Use pagination (limit + skip)
  • Inefficient projections → Always project only the needed fields
  • Type mismatches → Ensure field types match (e.g., number vs. string)
  • Mixing inclusion and exclusion in projections → Not allowed, except for _id

Comparing MongoDB find() to SQL

If you're coming from an SQL background, understanding how MongoDB’s find() compares to familiar SQL queries can make the transition easier. Here's a general comparison of common operations:

Concept

SQL Example

MongoDB Equivalent

Basic query

SELECT * FROM users WHERE age >= 18

db.users.find({ age: { $gte: 18 } })

Field selection

SELECT name, email FROM users

db.users.find({}, { name: 1, email: 1, _id: 0 })

Sorting

ORDER BY created_at DESC

.sort({ createdAt: -1 })

Limiting

LIMIT 10

.limit(10)

Skipping

OFFSET 10

.skip(10)

As you can see, MongoDB’s syntax is more JavaScript-like and expressive in JSON format, while SQL is more declarative and structured. Knowing these parallels will help you feel at home more quickly in MongoDB.

Summary and Best Practices

  • Think of find() as your data filter—combine conditions for precise results.
  • Always project only necessary fields for clarity and performance.
  • Use indexes to avoid slow scans.
  • Use Compass if you prefer visual feedback and faster iteration.
  • Take advantage of MongoDB Atlas's AI assistant to generate queries faster.
  • Explore advanced cursor options for fine-grained control over results.

Whether you’re building a startup dashboard, a data analytics tool, or an e-commerce back end, mastering find() will make your MongoDB experience smoother, faster, and more effective.

Stay tuned for more MongoDB insights in future articles!

Looking to validate your MongoDB skills? Read the Complete Guide to MongoDB Certification to explore your options.

Become a Data Engineer

Prove your skills as a job-ready data engineer.
Fast-Track My Data Career

FAQs

What is a cursor, practically speaking? Why doesn’t find() just give me an array of results?

MongoDB returns a cursor, which loads documents in batches (lazy loading). This is efficient for large collections but can confuse beginners expecting an array.

Why does find() have three parameters, but I usually see only two? Why is the third argument (options) rarely shown in examples?

Because most developers use chained methods like .sort(), .limit(), and .skip() instead of passing them in the options object. Some features (e.g., hint, readConcern, collation) require using the options document or separate method calls.

Why isn’t find() using the index I created? I created an index, but my find() query is still slow.

Not all queries automatically use indexes. Field order, data types, and collation settings can affect index usage. Use .explain("executionStats") to check whether MongoDB is using an index (IXSCAN) or doing a full scan (COLLSCAN).

Is my projection really improving performance? I’m projecting only two fields, but it doesn’t seem faster.

If the projected fields aren’t in an index, MongoDB still needs to fetch the full document from disk. Use covering indexes to serve the query entirely from the index, avoiding document lookups.

Can I use find() to group or summarize data? Can I count how many movies were released each year using find()?

No. find() is for retrieving documents. For grouping or summarizing, use the Aggregation Framework ($group, $count, etc.). While find() + .countDocuments() handles basic counts, real analytical needs should use .aggregate().

What is the difference between find() and findOne() in MongoDB?

 find() returns a cursor to all matching documents, while indOne() returns the first matching document directly. Use findOne() when you only need a single result.

How do I query an array field using find() in MongoDB?

You can match array elements directly. For example, { tags: "tech" } matches if "tech" is in the tags array. Use $elemMatch for more complex conditions.

Can I use regular expressions in MongoDB find() queries?

Yes, MongoDB supports regex patterns using syntax like { title: /sci-fi/i } to perform case-insensitive pattern matching on strings.

How do I use find() with a date range in MongoDB?

Use ISODate objects in the query. For example: { createdAt: { $gte: ISODate("2024-01-01"), $lte: ISODate("2024-12-31") } }.

What’s the performance impact of using find() without an index?

Queries on unindexed fields trigger full collection scans, which are slow for large datasets. Always index frequently queried fields.


Samuel Molling's photo
Author
Samuel Molling
LinkedIn

Samuel Molling is a Database Reliability Engineer passionate about automating and scaling secure data infrastructure in the cloud. 

Topics

Learn more about MongoDB and databases with these courses!

Course

Introduction to MongoDB in Python

4 hr
21.8K
Learn to manipulate and analyze flexibly structured data with MongoDB.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

blog

What Is MongoDB? Key Concepts, Use Cases, and Best Practices

This guide explains MongoDB, how it works, why developers love it, and how to start using this flexible NoSQL database.
Karen Zhang's photo

Karen Zhang

15 min

blog

Top 25 MongoDB Interview Questions and Answers for 2025

This guide covers essential MongoDB interview questions, from basics to advanced, with coding examples, real-world scenarios, and expert tips to help you succeed!
Srujana Maddula's photo

Srujana Maddula

12 min

Tutorial

MongoDB Aggregation Pipeline Tutorial in Python with PyMongo

Explore MongoDB aggregation pipelines using PyMongo. Understand data flow, stages like $match, $project, $group, $lookup, and advanced patterns.
Bex Tuychiev's photo

Bex Tuychiev

15 min

Tutorial

MongoDB Tutorial: How to Set Up and Query MongoDB Databases

Learn how to connect and analyze MongoDB databases in Python.
Bex Tuychiev's photo

Bex Tuychiev

10 min

Tutorial

A Comprehensive NoSQL Tutorial Using MongoDB

Learn about NoSQL databases - why NoSQL, how they differ from relational databases, the different types, and design your own NoSQL database using MongoDB.
Arunn Thevapalan's photo

Arunn Thevapalan

9 min

code-along

Getting Started in SQL

Learn how to write basic queries in SQL and find answers to business questions.
Kelsey McNeillie's photo

Kelsey McNeillie

See MoreSee More