Ir al contenido principal

Getting Started with MongoDB Query API

Master the MongoDB Query API with this comprehensive guide to CRUD operations, advanced filters, data aggregation, and performance-boosting indexing.
3 sept 2025  · 7 min de lectura

As a popular NoSQL database, MongoDB offers a flexible and scalable way to manage your data. This guide is your starting point for mastering its intuitive Query API, which allows you to interact with your data using a simple BSON (Binary JSON), which is optimized for efficiency and data types. 

Throughout this article, we'll cover the foundational create, read, update, delete (CRUD) operations, dive into precision querying with filters and projection, explore the power of aggregation pipelines for data transformation, and talk about indexing to boost performance. By the end, you'll have a strong foundation for efficiently retrieving and manipulating data in your MongoDB collections.

Foundational Concepts: CRUD Operations

The backbone of any database interaction is CRUD: create, read, update, and delete. Let's explore how to perform each one in MongoDB.

Creating data (insert)

To add new documents to a collection, you use the insert methods. Documents in MongoDB are JSON-like objects.

insertOne()

This method is used to add a single document to a collection.

// A sample document to insert
const newProduct = {
  name: "Wireless Mouse",
  brand: "Logitech",
  price: 29.99,
  inStock: true
};

// Insert the new document into the 'products' collection
db.products.insertOne(newProduct);

insertMany()

This method adds multiple documents at once, which is far more efficient than inserting them one by one.

// An array of documents to insert
const newProducts = [
  { name: "Mechanical Keyboard", brand: "Corsair", price: 129.99, inStock: false },
  { name: "Gaming Headset", brand: "Razer", price: 99.99, inStock: true },
  { name: "Webcam", brand: "LogiTech", price: 79.99, inStock: true }
];

// Insert the array of documents into the 'products' collection
db.products.insertMany(newProducts);

Reading data (find)

The find() method is your primary tool for retrieving documents from a collection. When you call find(), it doesn't immediately return all of the documents themselves. Instead, it returns a cursor. This is an efficient way to handle potentially large result sets without having to load everything into memory at once.

The simplest find() call takes no arguments and will return a cursor to every document in the collection.

// Find and return a cursor to all documents in the 'products' collection
db.products.find();

Here's an example of what that cursor object looks like in the mongosh (the MongoDB shell) and how you might interact with it:

// Find all products and assign the returned cursor to a variable
const productCursor = db.products.find();

// The variable 'productCursor' now holds the cursor object, not the documents themselves.
// To get the documents, you need to iterate over the cursor.

// You can convert the cursor to an array to see all the documents
const allProducts = productCursor.toArray();
console.log(allProducts);

// Or, you can manually iterate through the documents
while (productCursor.hasNext()) {
  const product = productCursor.next();
  console.log(product);
}

The cursor itself is an object with various methods like toArray(), hasNext(), and next() that allow you to retrieve and work with the documents in the result set.

Updating data (update)

To modify existing documents, you use the update methods. These methods take two main arguments: a filter to select the documents to update and an update operator to specify the changes. A common operator is $set, which sets the value of a field.

updateOne()

This method updates the first document that matches the filter.

// Update the 'Wireless Mouse' document to set its price to 39.99
db.products.updateOne(
  { name: "Wireless Mouse" }, // Filter to find the document
  { $set: { price: 39.99 } } // Update operator
);

updateMany()

This method updates all documents that match the specified filter.

// Update all 'LogiTech' brand products to be in stock
db.products.updateMany(
  { brand: "LogiTech" }, // Filter to find the documents
  { $set: { inStock: true } } // Update operator
);

Deleting data (delete)

To remove documents, you use the delete methods. These also take a filter to determine which documents to remove.

deleteOne()

This method removes the first document that matches the filter.

// Delete the 'Webcam' document
db.products.deleteOne({ name: "Webcam" });

deleteMany()

This method removes all documents that match the filter. To delete all documents in a collection, you can pass an empty filter {}.

// Delete all documents that are not in stock
db.products.deleteMany({ inStock: false });

Precision Retrieval: Query Filters

Query filters are at the heart of MongoDB's power. They are the first argument in find() and update methods and allow you to precisely select which documents you want to work with.

Comparison operators

These operators let you compare a field's value to a specified value.

$eq (equals)

This finds documents where a field is equal to a value.

// Find all products that are made by 'Razer'
db.products.find({ brand: { $eq: "Razer" } });
// This can be simplified to:
// db.products.find({ brand: "Razer" });

$gt and $gte (greater than, greater than or equal to)

These find documents where a field's value is greater than ($gt) or greater than or equal to ($gte) a specified value.

// Find all products with a price greater than 100
db.products.find({ price: { $gt: 100 } });

$lt and $lte (less than, less than or equal to)

These find documents where a field's value is less than ($lt) or less than or equal to ($lte) a specified value.

// Find all products with a price less than or equal to 50
db.products.find({ price: { $lte: 50 } });

$ne (not equal to)

$ne finds documents where a field is not equal to a specified value.

// Find all products that are NOT made by 'LogiTech'
db.products.find({ brand: { $ne: "LogiTech" } });

$in and $nin (in an array, not in an array)

These find documents where a field's value is in ($in) or not in ($nin) a specified array of values.

// Find all products from 'Razer' or 'Corsair'
db.products.find({ brand: { $in: ["Razer", "Corsair"] } });

Logical operators

Logical operators combine multiple conditions to create complex queries.

$and

$and combines query conditions with a logical AND. All conditions must be true.

// Find all products with a price greater than 50 AND are in stock
db.products.find({ $and: [{ price: { $gt: 50 } }, { inStock: true }] });
// This can be simplified by just listing the conditions:
// db.products.find({ price: { $gt: 50 }, inStock: true });

$or

This combines query conditions with a logical OR. At least one condition must be true.

// Find all products with a brand of 'Corsair' OR a price less than 40
db.products.find({ $or: [{ brand: "Corsair" }, { price: { $lt: 40 } }] });

Element and evaluation operators 

These operators provide even more flexibility for filtering.

$exists

$exists matches documents that contain a specific field.

// Find all documents that have an 'inStock' field
db.products.find({ inStock: { $exists: true } });

$regex

This allows you to use regular expressions for pattern matching in string fields.

// Find all product names that start with 'Wireless'
db.products.find({ name: { $regex: /^Wireless/ } });

Shaping Your Output: Projection

When you perform a find() operation, you can choose to receive only a subset of the fields in each document. This is called projection and it's the second argument you pass to find(). It helps reduce the amount of data transferred and processed.

Including fields

You can specify which fields to return by setting their value to 1.

// Find all products and return only the 'name' and 'price' fields
db.products.find({}, { name: 1, price: 1 });

Excluding fields

Conversely, you can specify which fields to hide by setting their value to 0.

// Find all products and hide the 'inStock' field
db.products.find({}, { inStock: 0 });

The _id field is always returned by default unless you explicitly exclude it.

The _id Field

To hide the _id field, you must explicitly set it to 0.

// Find all products, returning only 'name' and 'price', and hiding '_id'
db.products.find({}, { _id: 0, name: 1, price: 1 });

Advanced Data Transformation: Aggregation Pipelines

Aggregation is a powerful framework for data processing in MongoDB. An aggregation pipeline consists of a series of stages that process documents and pass the results from one stage to the next.

$match

A $match stage filters documents based on a query filter, just like in find(). This is often the first stage to reduce the number of documents to be processed.

// Find all products with a brand of 'LogiTech'
db.products.aggregate([
  { $match: { brand: "LogiTech" } }
]);

$group

The $group stage groups documents by a specified _id expression and can perform various accumulator operations, like calculating the sum or average of a field.

// Group products by brand and calculate the total number of products for each brand
db.products.aggregate([
  { $group: { _id: "$brand", totalProducts: { $sum: 1 } } }
]);

$project

A $project stage reshapes each document in the stream, similar to projection in find(). You can add new fields, remove existing ones, and manipulate data.

// Project a new field 'nameAndPrice' for each document
db.products.aggregate([
  { $project: { name: 1, price: 1, nameAndPrice: { $concat: ["$name", " (", "$price", ")"] } } }
]);

$sort

The $sort stage reorders the documents based on a specified field. The value 1 is for ascending order, and -1 is for descending.

// Sort all products by price in descending order
db.products.aggregate([
  { $sort: { price: -1 } }
]);

$limit and $skip

These stages are used for pagination. $skip discards a specified number of documents from the beginning of the pipeline, and $limit restricts the number of documents passed to the next stage.

// Skip the first 10 products and then return the next 5
db.products.aggregate([
  { $skip: 10 },
  { $limit: 5 }
]);

A simple pipeline example

Here is a complete example that shows how these stages work together.

// Find the average price of all products that are currently in stock,
// grouped by brand.
db.products.aggregate([
  { $match: { inStock: true } }, // Filter for products in stock
  { $group: { _id: "$brand", averagePrice: { $avg: "$price" } } } // Group and calculate average price
]);

Boosting Performance: Indexing

Indexes are special data structures that store a small, easily traversable portion of a collection's data. They significantly improve query performance by allowing MongoDB to quickly find and retrieve documents without scanning the entire collection.

createIndex()

You create an index on a field that you frequently query or sort by.

// Create a single-field index on the 'brand' field
db.products.createIndex({ brand: 1 });

The 1 indicates an ascending order for the index. You can use -1 for descending order, which can be beneficial for queries that sort in that direction.

Creating an index on a field like brand will make queries that filter by brand (e.g., db.products.find({ brand: "Razer" })) execute much faster, especially as your collection grows.

Considerations for choosing fields to index

You should typically create indexes on fields that you frequently use in your queries, such as those in a find() filter or an aggregation's $match stage.

  • Cardinality: Fields with many unique values (high cardinality), like a user's email address, are excellent candidates for indexes.
  • Query selectivity: A field that returns a small subset of documents for a given query is also a great candidate.
  • Sorting: If you frequently sort your query results by a particular field, creating an index on that field will make the sort operation much faster.

Impact on queries

Indexes have a significant impact on performance. A query with an index will often be orders of magnitude faster than the same query without one.

// Conceptual illustration of performance difference

// Without an index on 'brand':
// MongoDB performs a full collection scan, checking every document.
// This is slow, especially with millions of documents.
db.products.find({ brand: "Razer" });

// With an index on 'brand':
// MongoDB uses the index to quickly locate and return only the matching documents.
// This is very fast.
db.products.find({ brand: "Razer" });

To further optimize queries, you can use the db.collection.explain() method to analyze query performance and see how indexes are being utilized.

Conclusion: Your Journey to MongoDB Proficiency

You've just completed a crash course in MongoDB's Query API! You now know how to perform core CRUD operations, use powerful filters to retrieve specific data, shape your output with projection, and transform your data with aggregation pipelines. You also have a basic understanding of indexing to improve performance.

This guide provides a solid foundation, and the best way to master these concepts is to practice them. I encourage you to experiment with different queries and explore the full documentation to discover more advanced operators and features. Happy coding!

MongoDB Query API FAQs

What is the main difference between find() and aggregate()?

The find() method is used for simple document retrieval with optional filtering and projection. The aggregate() method, on the other hand, is a powerful framework for multi-stage data processing, allowing you to transform, group, sort, and reshape documents in a more complex way. While find() is for reading documents as they are, aggregate() is for deriving new insights from your data.

Why does MongoDB return a cursor from a find() operation instead of the actual documents?

A cursor is an efficient way to handle potentially large result sets. By returning a cursor, MongoDB avoids loading all the documents into memory at once. This is crucial for performance and scalability, especially when dealing with millions of documents. The cursor allows you to iterate over the results as needed, fetching documents in batches.

When should I use updateOne() vs. updateMany()?

Use updateOne() when you need to modify only the first document that matches your specified filter. This is ideal for scenarios where you expect only one document to match, such as when you're filtering by a unique identifier. Use updateMany() when you want to update every document that meets the filter criteria.

How do indexes improve query performance?

Indexes are special data structures that store a small, organized subset of a collection's data. They significantly speed up queries by allowing MongoDB to quickly locate documents without having to scan the entire collection. Instead of checking every document one by one, the database can use the index to jump directly to the matching documents, making the operation orders of magnitude faster.

Can I mix projection with aggregation?

Yes, projection is a key part of the aggregation pipeline. The $project stage is used to reshape documents, add new fields, or remove existing ones. It's often used after other stages like $match or $group to format the output of the pipeline, providing you with fine-grained control over the final structure of your data.


Karen Zhang's photo
Author
Karen Zhang
LinkedIn

Karen is a Data Engineer with a passion for building scalable data platforms. She has experience in infrastructure automation with Terraform and is excited to share her learnings in blog posts and tutorials. Karen is a community builder, and she is passionate about fostering connections among data professionals.

Temas

Top Courses

Programa

Ingeniero de datos en Python

0 min
Adquiere habilidades demandadas para ingerir, limpiar y gestionar datos de forma eficaz, así como para programar y supervisar canalizaciones, lo que te diferenciará en el campo de la ingeniería de datos.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado

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 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.
Samuel Molling's photo

Samuel Molling

Tutorial

MongoDB Dot Notation Tutorial: Querying Nested Fields

Learn a few querying techniques for nested documents and arrays within MongoDB.
Nic Raboy's photo

Nic Raboy

Tutorial

How to Create a Database in MongoDB: A Quick Guide

Discover how to create a MongoDB database from the shell or with a script, plus common pitfalls to avoid.
Nic Raboy's photo

Nic Raboy

Tutorial

How to Install MongoDB on Ubuntu: A Step-by-Step Guide for Beginners

Learn how to install MongoDB on Ubuntu, configure the service, and verify the setup in this beginner-friendly tutorial.
Nic Raboy's photo

Nic Raboy

Ver másVer más