🍃 MongoDB Tutorial

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 last age key would apply) — use explicit $and: [{age:{$gte:20}}, {age:{$lte:30}}] whenever the same field needs two conditions.
  • $or returning way more than expected — $or only 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 $not with $ne — $not wraps a whole operator expression ({ field: { $not: { $gt: 5 } } }), while $ne is itself a comparison operator ({ field: { $ne: 5 } }) — they aren't interchangeable syntax.

Key Takeaways

  • $and and simply chaining fields in one object are usually equivalent — use explicit $and for repeated fields.
  • $or and $nor are opposites: "at least one true" vs. "all false."
  • $not wraps a single condition and negates it — it's not the same as $ne.