How query filters work
Every MongoDB query starts with a filter — a JSON-like document that describes what you’re looking for. Think of it as a bouncer at the door: every document in the collection has to pass your filter to make it into the result set. A simple filter like{ status: "active" } is an equality check. A more advanced filter like { age: { $gte: 18 } } uses an operator to say “18 or older.” You can also use dot notation to reach inside nested documents ("profile.country") and special operators to query arrays and embedded objects.
Your everyday toolkit: the most common operators
Equality — the bread and butter
When you know the exact value you want, just ask for it:$eq matches documents where a field equals the specified value. In most cases, the short form { field: value } does the same thing and reads more naturally. You’ll almost always use the short form.
Not equal — the “anything but this” filter
Use$ne to exclude a specific value:
$ne also matches documents where the field doesn’t exist at all. This catches people off guard more often than you’d think!
nin — the “pick from the menu” operators
When a field could match any value from a list,$in is your best friend:
$in matches when the field equals any value in your array. Bonus: if the field itself is an array, $in matches when at least one element overlaps. It’s like a Venn diagram in one line of code.
Range comparisons — the number crunchers
Use these when you need “greater than,” “less than,” or “between”:$gt, $gte, $lt, and $lte. They work on numbers, dates, and any sortable BSON type. Pro-tip: You can stack two range operators on the same field to create a “between” filter, like the qty example above.
$exists — the “is it even there?” check
Sometimes you just need to know whether a field is present:null still counts as existing. If you want “field is missing entirely,” use $exists: false.
$regex — the pattern matcher
When you need fuzzy matching on strings, regex has your back:^sam is the sweet spot — MongoDB can actually use an index for it, so it’s fast. Unanchored patterns like "sam" or ".*sam.*" are much more expensive because MongoDB has to check every value. Use regex when you need it, but prefer exact equality when you can.
Logical operators — the combinators
Need to combine multiple conditions? These are your tools:$and means “all of these must be true.” $or means “at least one must be true.” MongoDB also supports $not and $nor for negation. Pro-tip: When you put multiple conditions on different fields in a single filter document, MongoDB treats them as an implicit $and — so you often don’t need to write $and explicitly.
Querying nested fields
MongoDB uses dot notation to reach inside embedded documents, just like accessing properties in JavaScript:Querying arrays: where MongoDB gets interesting
Arrays are one of the places where MongoDB really diverges from SQL-style thinking. Here’s how to work with them:Match any element in an array
tags is an array, MongoDB automatically checks whether any element matches. You don’t need special syntax — it just works.
Match multiple conditions on the same element
This is where things get tricky. If you have an array of objects and need multiple conditions to apply to the same element (not spread across different elements), you need$elemMatch:
$elemMatch, MongoDB might match a document where one element has product: "xyz" and a completely different element has score >= 8. That’s almost never what you want.
Real-world patterns you’ll use all the time
Find active users created this year
Find documents with missing data
$exists: false means “the field is absent,” not “the field is null.”
Case-insensitive email domain search
Match one of several statuses
$or with separate equality checks on the same field.
Performance: keeping your queries fast
Not all operators are created equal when it comes to speed:- Exact matches and selective ranges are the fastest — they play nicely with indexes.
$neand$ninare valid but often broader than you’d expect (remember,$nematches missing fields too). They tend to scan more data.- Prefix regex (
^abc) can use indexes. Unanchored regex cannot. $existscan be tricky — consider whether a partial index might serve you better.
.explain("executionStats") on your query. It’ll tell you exactly whether an index was used and how many documents MongoDB had to examine. If you’re scanning 100,000 documents to return 5, something needs a rethink.
Common mistakes (and how to avoid them)
Confusing null with missing
These are not the same in MongoDB. A field can exist with the valuenull, which means $exists: true still matches it. If you need “field is truly absent,” use $exists: false. If you need “field is null,” query for { field: null } directly.
Forgetting $elemMatch on arrays of objects
Without$elemMatch, your conditions can match across different array elements. This is one of the most common bugs in MongoDB queries — and one of the hardest to spot because the query doesn’t error, it just returns wrong results.
Reaching for regex when equality would do
Regex is flexible, but it’s like driving a truck to the corner store. If you know the exact value, use equality. If you know the prefix, use an anchored regex. Save the expensive unanchored patterns for when you truly need them.Operator cheat sheet
| Operator | Purpose | Example |
|---|---|---|
$eq | Exact match | { status: { $eq: "active" } } |
$ne | Not equal | { status: { $ne: "archived" } } |
$in | Match any of several values | { tier: { $in: ["free", "pro"] } } |
$gt / $gte | Greater than / greater than or equal | { score: { $gte: 80 } } |
$lt / $lte | Less than / less than or equal | { age: { $lt: 30 } } |
$exists | Field present or absent | { deletedAt: { $exists: false } } |
$regex | Pattern match | { name: { $regex: "^sam", $options: "i" } } |
$and | All conditions must match | { $and: [{ a: 1 }, { b: 2 }] } |
$or | Any condition may match | { $or: [{ status: "trial" }, { seats: { $gte: 50 } }] } |
$elemMatch | Multiple conditions on one array element | { items: { $elemMatch: { sku: "A1", qty: { $gte: 2 } } } } |
Summary
Query operators are the building blocks of everything you do in MongoDB — from simple lookups to complex aggregation pipelines. Master the handful covered here and you’ll be able to express almost any filter your app needs. Use them in collection filters, saved queries, and early$match stages in your pipelines. And when in doubt, run an explain plan — with tools like Spanna Pro to help you visualize query performance, you’ll always know exactly what MongoDB is doing under the hood.
