MongoDB $and Operator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $and?

$and is MongoDB’s logical AND. Every expression in the array must be true for the result to be true. Use it as an aggregation expression (returns a boolean) or in queries / $match (keeps matching documents).

Remember
$and = every condition must pass

{ $and: [ <expr1>, <expr2>, ... ] }

aggregation → true / false
$match / find → keep docs that match all

falsy: false, null, 0, undefined
truthy: non-zero numbers, strings, arrays
empty array → true (aggregation)
UsePrefer
All conditions must pass$and
At least one condition$or
Flip a boolean$not

How to Use $and in MongoDB

Pick the mode that matches your goal: compute a boolean, or filter documents.

  1. List every condition that must be true (comparisons, field checks, nested expressions).
  2. Wrap them in { $and: [ ... ] }.
  3. For a boolean field, put that expression in $addFields or $project.
  4. To filter rows, put $and inside $match (or find()).
PieceRequired?Role
$andYesLogical AND over an array
ExpressionsYes (usually 2+)Each must be truthy for a true result
Stage / queryYes$project / $addFields for flags; $match to filter

Pseudocode

Pseudocode
for each document:
    result = true
    for each expression in $and array:
        value = evaluate(expression)
        if value is falsy (false, null, 0, undefined):
            result = false
            break
    // aggregation: emit boolean
    // $match: keep document only if result is true

Cheat Sheet

Keep these facts handy while writing AND logic.

TopicDetail
TypeLogical operator (query + aggregation expression)
Syntax{ $and: [ <expr1>, <expr2>, ... ] }
Aggregation resulttrue only if every expression is truthy
Empty array{ $and: [] } → true
Range pattern$and: [ { $gt: ["$qty", 100] }, { $lt: ["$qty", 250] } ]
Implicit AND{ a: 1, b: 2 } already means both fields must match
vs $orAND = all; OR = any

Live Preview

Simulate $and: [ { $gt: ["$qty", 100] }, { $lt: ["$qty", 250] } ]. Change quantity and watch each check and the final AND result.

Same idea as the mongosh examples: qty must be greater than 100 and less than 250.

Result
qty = 180
$gt(qty, 100) → true
$lt(qty, 250) → true
$and → true

{ qty: 180, inRange: true }

Worked Walkthrough — Quantity in Range

Rule: a product is “in range” when qty > 100 and qty < 250. Trace a few values.

Calculation
Rule:
  $and([ qty > 100, qty < 250 ])

qty = 180
  180 > 100 → true
  180 < 250 → true
  $and → true   ✓

qty = 300
  300 > 100 → true
  300 < 250 → false
  $and → false  ✗

qty = 80
  80 > 100 → false
  80 < 250 → true
  $and → false  ✗

One false kills the whole AND.

MongoDB Examples

We use a small inventory collection. First we compute an inRange boolean, then we filter with $match. Insert the sample data once in mongosh.

Example 1 — Sample Data

Imagine five inventory items. Each document has an item code and a quantity. We save them in a collection named inventory.

mongosh
db.inventory.insertMany([
  { _id: 1, item: "abc1", qty: 300 },
  { _id: 2, item: "abc2", qty: 200 },
  { _id: 3, item: "xyz1", qty: 250 },
  { _id: 4, item: "VWZ1", qty: 300 },
  { _id: 5, item: "VWZ2", qty: 180 }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps five documents in inventory. Run find() to see them:

mongosh
db.inventory.find()

Read those documents like this:

Field in MongoDBExamplePlain English
_id1 … 5Document id for this lesson
item"abc2"Product / SKU code
qty200Quantity on hand
Picture
In-range window (exclusive):

  qty > 100  AND  qty < 250

          |---- in range ----|
  --------+------------------+--------
        100                250

  180, 200 → inside  → true
  250, 300 → outside → false
   80      → outside → false

How It Works

  1. Insert once. insertMany adds five inventory documents.
  2. MongoDB stores fields as written. Each row keeps item and qty as plain values.
  3. find() shows the same shape. What you inserted is what you get back—ready for $and next.

Example 2 — Boolean Flag with $and

Goal: add inRange: true/false without removing documents. Check qty > 100 and qty < 250.

mongosh
db.inventory.aggregate([
  {
    $addFields: {
      inRange: {
        $and: [
          { $gt: ["$qty", 100] },
          { $lt: ["$qty", 250] }
        ]
      }
    }
  }
]);

How It Works

  1. Read qty. For each stored document, MongoDB evaluates "$qty".
  2. Check both sides. $gt asks “greater than 100?” and $lt asks “less than 250?”.
  3. AND them. $and returns true only when both checks pass (200 and 180).
  4. Keep all rows. $addFields adds inRange; nothing is filtered out yet.

Example 3 — Filter with $match

Same rule, but keep only documents where the AND is true. Wrap the aggregation expression in $expr.

mongosh
db.inventory.aggregate([
  {
    $match: {
      $expr: {
        $and: [
          { $gt: ["$qty", 100] },
          { $lt: ["$qty", 250] }
        ]
      }
    }
  }
]);

How It Works

  1. Same stored documents. Still using the five rows from Example 1.
  2. Same two checks. qty must be > 100 and < 250.
  3. $expr unlocks expression ops. Inside $match, $gt / $lt need $expr.
  4. Filter, don’t flag. Only abc2 and VWZ2 survive—the rows that were inRange: true in Example 2.

Edge Cases & Pitfalls

Check these before shipping $and logic.

falsy

0 and null count as false

Aggregation $and treats 0, null, and undefined as false—not only the boolean false.

arrays

Arrays are truthy

[false] is still an array, so it counts as true. Use $allElementsTrue when you mean “every element is true.”

implicit

Don’t overuse explicit $and

Different fields can often use implicit AND: { status: "A", qty: { $gt: 0 } }. Prefer explicit $and when it improves clarity or you need expression mode.

errors

Errors are not always short-circuited

A later expression may still error even if an earlier one is false. Validate risky math before relying on AND order.

Performance Notes

ApproachCostBest for
$and in $match (query form)Can use indexesEarly filtering on stored fields
$expr + $andExpression eval per docField-to-field comparisons
$and in $addFieldsPer-document booleanFlags / reports without dropping rows

Put selective filters first with $match so later stages process fewer documents. Prefer indexed query predicates when you do not need $expr.

Key Takeaways

  • Role: all conditions must pass (logical AND).
  • Modes: boolean flag in aggregation, or filter in $match.
  • Falsy: false, null, 0, undefined.
  • vs OR: use $or when any one condition is enough.

One line: $and answers “are all of these true?”—as a boolean in aggregation, or as a multi-condition filter in $match.

Frequently Asked Questions

$and performs a logical AND on an array of expressions. In aggregation, it returns true only when every expression is truthy. In queries and $match, a document must satisfy every condition inside $and.
Use { $and: [ <expression1>, <expression2>, ... ] }. Pass an array of expressions. An empty array returns true in aggregation.
Use it when you need clear multi-condition logic, multiple separate condition objects, or an aggregation boolean flag. Simple { a: 1, b: 2 } already means AND for different fields.
In aggregation, false, null, 0, and undefined count as false. Non-zero numbers, non-empty strings, and arrays count as true—even arrays that contain false.
Yes. Put field conditions directly in $and, or wrap aggregation comparisons with $expr when you need expression operators.
$and requires every condition to pass. $or requires at least one condition to pass.

Next: $anyElementTrue

Check whether any value inside an array is true.

$anyElementTrue tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful