MongoDB Logical Operators: $and, $or, $nor, $not (With Examples)
Learn how to combine multiple MongoDB query conditions using $and, $or, $nor and $not — with practical examples and common pitfalls.
MongoDB Logical Operators
Logical operators let you combine two or more conditions into a single query.
| Operator | Description |
|---|---|
$and |
Matches documents that satisfy all the given conditions |
$or |
Matches documents that satisfy at least one condition |
$nor |
Matches documents that satisfy none of the conditions |
$not |
Matches documents that do not match the given expression |
$and
Joins conditions with a logical AND. It short-circuits — if an earlier condition is false, later ones aren't even checked.
// age should be >= 25 AND city should be Palghar
db.employees.find({
$and: [
{ age: { $gte: 25 } },
{ city: { $eq: 'Palghar' } }
]
})
This is equivalent to simply listing both fields in one object:
db.employees.find({
age: { $gte: 25 },
city: { $eq: 'Palghar' }
})
You only need the explicit $and: [...] form when you need the same field twice with different conditions, or want to be fully explicit.
$or
Matches if any of the listed conditions is true.
// age >= 25 OR city is Palghar
db.employees.find({
$or: [
{ age: { $gte: 25 } },
{ city: { $eq: 'Palghar' } }
]
})
Unlike $and, $or won't error even if one of the fields doesn't exist on any document — it just relies on the other condition matching.
$nor
The opposite of $or — matches documents where every listed condition is false.
// age is NOT >= 25, AND city is NOT Pune
db.employees.find({
$nor: [
{ age: { $gte: 25 } },
{ city: { $eq: 'Pune' } }
]
})
$not
Negates a single expression. It also matches documents where the field is missing entirely.
db.employees.find({ salary: { $not: { $gt: 20000 } } })
// salary is less than or equal to 20000
db.employees.find({ gender: { $not: { $eq: "F" } } })
// gender is not F (i.e. M, or missing)
Common Errors & Troubleshooting
- Duplicate field names silently overwriting each other —
{ age: {$gte:20}, age: {$lte:30} }in one plain object is invalid (only the lastagekey would apply) — use explicit$and: [{age:{$gte:20}}, {age:{$lte:30}}]whenever the same field needs two conditions. $orreturning way more than expected —$oronly needs ONE branch to match. If one branch is too broad (e.g. a typo'd field name that matches every document because the field doesn't exist), the whole query matches everything.- Confusing
$notwith$ne—$notwraps a whole operator expression ({ field: { $not: { $gt: 5 } } }), while$neis itself a comparison operator ({ field: { $ne: 5 } }) — they aren't interchangeable syntax.
Key Takeaways
$andand simply chaining fields in one object are usually equivalent — use explicit$andfor repeated fields.$orand$norare opposites: "at least one true" vs. "all false."$notwraps a single condition and negates it — it's not the same as$ne.