R
Rishtaara
MongoDB Fundamentals
Lesson 19 of 40Article14 min

Logical Operators

Logical operators combine multiple conditions. $and requires all conditions true. $or requires at least one. $not negates an expression. $nor matches documents where none of the conditions are true.

$and, $or, $not, $nor

Logical operators combine multiple conditions. $and requires all conditions true. $or requires at least one. $not negates an expression. $nor matches documents where none of the conditions are true.

Real-life example: $or is like a menu combo — pizza OR pasta qualifies. $and is like needing both a ticket AND an ID to enter.

All four logical operators
use rishtaara

// $or — electronics OR furniture under ₹500
db.products.find({
  $or: [
    { category: "electronics", price: { $lt: 500 } },
    { category: "furniture", price: { $lt: 500 } }
  ]
})

// $and — explicit (usually implicit between top-level fields)
db.students.find({
  $and: [
    { active: true },
    { grade: { $in: [11, 12] } },
    { "address.city": "Bengaluru" }
  ]
})

// $not — negates the condition inside
db.products.find({
  price: { $not: { $gt: 1000 } }
})
// price <= 1000 OR price is non-numeric/null

// $nor — none of these conditions may be true
db.students.find({
  $nor: [
    { grade: { $lt: 9 } },
    { active: false }
  ]
})
// grade >= 9 AND active is not false

Implicit AND vs explicit $and

When you list multiple fields in a find filter, MongoDB applies implicit AND — every condition must match. Use explicit $and when you need multiple conditions on the same field or complex nesting.

Real-life example: Implicit AND is like a checklist where every box must be ticked. Explicit $and is needed when you check the same box twice with different rules.

Use parentheses-style nesting with $and and $or for readability. A query that is hard to read in code is hard to debug in production.
Implicit AND — most common
// Implicit AND — all three must match
db.products.find({
  category: "electronics",
  price: { $lt: 2000 },
  stock: { $gt: 0 }
})

// Equivalent explicit $and
db.products.find({
  $and: [
    { category: "electronics" },
    { price: { $lt: 2000 } },
    { stock: { $gt: 0 } }
  ]
})
When explicit $and is required
// Multiple conditions on the SAME field — need $and
db.products.find({
  $and: [
    { price: { $gte: 100 } },
    { price: { $lte: 500 } }
  ]
})
// Same as: db.products.find({ price: { $gte: 100, $lte: 500 } })

// Complex mix: (grade 10 OR 11) AND active AND in Delhi
db.students.find({
  $and: [
    { $or: [{ grade: 10 }, { grade: 11 }] },
    { active: true },
    { "address.city": "Delhi" }
  ]
})

// ⚠️ Use parentheses logic — $or binds less tightly than you might expect
// Always use explicit $and/$or for complex filters

Real-world filter combinations

Product search and student dashboards combine logical operators daily. Test each filter in mongosh, then copy to your API.

Real-life example: A 'Deals page' query is $or across categories plus $and for price and stock — marketing logic as database filters.

  • $nor is rarely used but useful for 'exclude if any of these match' logic.
  • $not wraps a single expression — different from $ne which compares to a value.
  • Index intersection can help $or queries — but compound indexes on $and patterns are more predictable.
E-commerce search filters
// Deals: (electronics under ₹1000) OR (stationery under ₹100), in stock
db.products.find({
  $and: [
    { stock: { $gt: 0 } },
    {
      $or: [
        { category: "electronics", price: { $lt: 1000 } },
        { category: "stationery", price: { $lt: 100 } }
      ]
    }
  ]
})

// Exclude clearance and archived unless on sale
db.products.find({
  $or: [
    { onSale: true },
    {
      $and: [
        { category: { $nin: ["clearance", "archived"] } },
        { status: { $ne: "hidden" } }
      ]
    }
  ]
})
Student dashboard queries
// Active students in Delhi or Mumbai, grade 10+
db.students.find({
  active: true,
  grade: { $gte: 10 },
  $or: [
    { "address.city": "Delhi" },
    { "address.city": "Mumbai" }
  ]
})

// Students missing email OR phone (incomplete profiles)
db.students.find({
  $or: [
    { email: { $exists: false } },
    { email: null },
    { phone: { $exists: false } }
  ]
})