MongoDB is fast, flexible, and easy to get started with, but it’s also easy to misuse. If you’re working with a growing codebase or dataset, it’s likely you’ve already run into performance slowdowns or overly complex queries that are hard to debug.
In this post, we’ll explore 6 common MongoDB query mistakes developers make (even experienced ones!) and how to fix them. Along the way, we’ll show you how Mongo Pilot, and our visual query builder and optimization assistant, helps you write better queries, explore data faster, and test changes like index creation safely before touching production. Let’s start!
1. Forgetting to use Indexes:
The mistake:
Writing Mongo DB queries without considering indexes at all.
When MongoDB has no index to support a query, it must scan every document in the collection. On small datasets, this might not seem like a big deal, but once you scale, this turns into a major performance bottleneck.
How to fix it:
- Identify which fields are used in find, sort, or joins via $lookup.
- Add appropriate indexes.
- Use .explain() or query stats to see how well your queries perform.
- With Mongo Pilot, benchmark new index safely before deplyoing it.
- Read our guide about MongoDB indexes and why they matter
Real world example
You have users collection with 1 million documents and run:
db.users.find({ email: "[email protected]" });Without an index an email field:
- Execution time: ~800 ms
- Documents scanned: 1,000,000
- Returned: 1
- CPU usage: High
With an index on email field:
- Execution time: ~4 ms
- Documents scanned: 1
- Returned: 1
- CPU usage: Minimal
How to benchmark and validate the impact before adding it to production? You can do it with Mongo Pilot, a smart MongoDB GUI:
2. Returning More Data Than You Need
The mistake:
Writing queries that fetch entire documents when you only need one or two fields.
db.users.find({ country: "France" });
If you just want the names and emails, don’t pull full documents.
How to fix it:
Use projections to reduce network load and improve performance:
db.users.find(
{ country: "France" },
{ name: 1, email: 1, _id: 0 }
);Less data sent = faster response and less memory usage but also less processing frontend side.
With Mongo Pilot use the Visual pipeline editor to define extactly which fields you want without writing the syntax manually.

Read our beginners tutorial on MongoDB Aggregation pipelines.
3. Inefficient use of $in and $or
The mistake:
Using $in or $or on unindexed fields, or with huge lists, leading to full collection scans.
db.products.find({
$or: [
{ category: "shoes" },
{ category: "bags" },
{ category: "hats" }
]
});
How to fix it:
- Ensure the field used in
$inor$orhas an index.
- Consider breaking complex
$orconditions into multiple queries if necessary.
Mongo Pilot allows to see the execution plan and query stats live.
4. Ignoring the Power of Aggregation Pipelines
The mistake:
Writing multiple queries and client-side code instead of using MongoDB’s built-in aggregation framework.
// Inefficient: fetch + process manually
const users = db.users.find().toArray();
const emails = users.map(u => u.email);How to fix it:
Let MongoDB do the work on the server:
db.users.aggregate([
{ $project: { email: 1, _id: 0 } }
]);
Aggregation pipelines are powerful and reduce network traffic and client-side processing. In Mongo Pilot, you can easily build drag-and-drop aggregation pipelines. You can also debug the output of each stage.
5. Blindly Trusting Query Results Without Debugging
The mistake:
Assuming your query is efficient just it returns correct data. Many slow queries just “work”, they just don’t scale when data volume gets bigger.
How to fix it:
- Use
.explain("executionStats")to inspect real performance.
- Monitor
nReturned,docsExamined, andexecutionTimeMillis.
- Watch for collection scans.
In Mongo Pilot, when you run a query you can click on stats button and get these stats.

6. Poor Schema Design Hurting Query Efficiency
The Mistake:
Modeling your documents based only on real-world relationships, not how data will actually be queried.
How to Fix it:
Model based on access patterns:
- Embed related data that’s often queried together
- Denormalize where it improves performance
- Avoid excessive
$lookupjoins
Bad schema example:
{
orderId: "abc123",
userId: "user456",
items: [ { productId: "prod789", quantity: 2 } ]
}
You need a $lookup to get user data every time.
Better schema:
{
orderId: "abc123",
user: {
userId: "user456",
name: "Jane Doe",
email: "[email protected]"
},
items: [ { productId: "prod789", quantity: 2 } ]
}
Now your most common query (show order + user) is fast and self-contained.
Mongo Pilot Bonus:
Visualize and test queries against your current schema. See what data is missing and adapt your design based on real-world query patterns.
1000+ Developers took our MongoDB Quiz Challenge, Take it now and see how you score against others!
Final thoughts:
MongoDB gives you power and flexibility but that power comes with responsibility. Writing slow queries, misusing $in, or forgetting indexes can seriously hurt your app’s performance at scale.
The good news?
Tools like Mongo Pilot are here to help. You can now:
✅ Build queries visually
✅ Test and debug with real query stats
✅ Benchmark indexes safely before deploying
✅ Explore aggregation pipelines intuitively
Try Mongo Pilot for free today and build MongoDB queries like a pro.
