MongoDB $expr Operator

Beginner
⏱️ 9 min read
📚 Updated: Jul 2026
🎯 4 Examples
Query Expression

What You’ll Learn

The $expr operator lets you use aggregation expressions inside find() queries and $match stages. It unlocks field-to-field comparisons, arithmetic filters, and dynamic conditions that standard query operators cannot handle alone.

01

Expression Queries

Aggregation ops in filters.

02

Syntax

{ $expr: { ... } }

03

Field vs Field

Compare two document fields.

04

$match Stage

Filter in aggregation pipelines.

05

Use Cases

Budget checks, validation.

06

$ Prefix Fields

"$field" inside expressions.

Definition and Usage

In MongoDB, the $expr operator bridges query filters and aggregation expressions. Standard query operators like { salary: { $gt: 50000 } } compare a field to a literal value. With $expr, you can write { $expr: { $gt: [ "$spent", "$budget" ] } } to find documents where one field exceeds another — something regular queries cannot do directly.

💡
Beginner Tip

Inside $expr, field names need a $ prefix: "$spent", not "spent". This is aggregation expression syntax. Wrap comparison operators like $gt, $eq, or $and inside $expr.

📝 Syntax

The $expr operator wraps any aggregation expression for use in a query filter:

mongosh
{ $expr: <aggregation expression> }

Common patterns inside $expr:

mongosh
// Compare two fields:
{ $expr: { $gt: [ "$spent", "$budget" ] } }

// Combine conditions:
{ $expr: { $and: [
    { $eq: [ "$status", "active" ] },
    { $gte: [ "$score", 80 ] }
] } }

Syntax Rules

  • $expr — wraps an aggregation expression for use in find() or $match.
  • Field references — use "$fieldName" with a dollar sign inside the expression.
  • Supports comparison operators: $eq, $gt, $gte, $lt, $lte, $ne.
  • Supports logical operators: $and, $or, $not.
  • Supports arithmetic: $add, $subtract, $multiply, $divide.

💡 Standard Query vs $expr

Know when you need $expr:

Standard: { salary: { $gt: 50000 } } (field vs literal)
$expr: { $expr: { $gt: [ "$spent", "$budget" ] } } (field vs field)
Use $expr when comparing fields or doing math in filters

⚡ Quick Reference

QuestionAnswer
Operator typeQuery operator (wraps aggregation expressions)
Syntax{ $expr: <aggregation expression> }
Field references"$fieldName" with $ prefix
Key use caseCompare two fields on the same document
Common stagesfind(), $match
Field vs field
{
  $expr: {
    $gt: [
      "$spent",
      "$budget"
    ]
  }
}

spent > budget

With $and
{
  $expr: {
    $and: [
      { $eq: ["$status","active"] },
      { $gte: ["$score", 80] }
    ]
  }
}

Multiple conditions

Arithmetic
{
  $expr: {
    $lt: [
      "$salePrice",
      { $multiply: ["$price", 0.5] }
    ]
  }
}

sale < 50% of price

In $match
{
  $match: {
    $expr: {
      $eq: ["$dept","Sales"]
    }
  }
}

Aggregation pipeline

Examples Gallery

Walk through sample budget data, filter documents where spending exceeds budget using $expr, and explore arithmetic and compound conditions.

📚 Compare Two Fields

Use a departments collection and find records where spent exceeds budget with $expr.

Sample Input Documents

Suppose you have a departments collection tracking spending against budget:

mongosh
[
  { "_id": ObjectId("609c26812e9274a86871bc6a"), "name": "Marketing", "budget": 10000, "spent": 12500 },
  { "_id": ObjectId("609c26812e9274a86871bc6b"), "name": "Engineering", "budget": 50000, "spent": 42000 },
  { "_id": ObjectId("609c26812e9274a86871bc6c"), "name": "Sales", "budget": 8000, "spent": 9500 }
]

Example 1 — Find Over-Budget Departments

Use $expr to compare two fields on the same document:

mongosh
db.departments.find({
  $expr: {
    $gt: [ "$spent", "$budget" ]
  }
})

How It Works

  • Marketing: 12500 > 10000 → matched (over budget).
  • Engineering: 42000 > 50000 → excluded (under budget).
  • Sales: 9500 > 8000 → matched (over budget).
  • A standard query like { spent: { $gt: 10000 } } cannot compare two fields.

📈 Practical Patterns

Combine $expr with arithmetic, logical operators, and aggregation pipelines.

Example 2 — Arithmetic in a Filter

Find products where the sale price is less than half the original price:

mongosh
db.products.find({
  $expr: {
    $lt: [
      "$salePrice",
      { $multiply: [ "$price", 0.5 ] }
    ]
  }
})

How It Works

$multiply computes half the original price inside the filter. $lt then compares salePrice against that computed value.

Example 3 — Multiple Conditions with $and

Find active employees with a score of at least 80:

mongosh
db.employees.find({
  $expr: {
    $and: [
      { $eq: [ "$status", "active" ] },
      { $gte: [ "$score", 80 ] }
    ]
  }
})

How It Works

Both conditions inside $and must be true. This pattern works when you need aggregation-style comparisons in a standard find() query.

Example 4 — $expr in an Aggregation $match Stage

The same syntax works inside aggregation pipelines:

mongosh
db.departments.aggregate([
  {
    $match: {
      $expr: {
        $gt: [ "$spent", "$budget" ]
      }
    }
  },
  {
    $project: {
      name: 1,
      budget: 1,
      spent: 1,
      overspend: {
        $subtract: [ "$spent", "$budget" ]
      }
    }
  }
])

How It Works

$expr filters over-budget departments in $match, then a later $project stage computes how much each department overspent.

🚀 Use Cases

  • Field-to-field comparisons — find documents where spent > budget, actual ≠ expected, or similar cross-field checks.
  • Arithmetic filters — filter based on computed values like sale price below 50% of original price.
  • Dynamic validation — flag records that fail business rules expressed as aggregation expressions.
  • Complex conditions — combine $and, $or, and comparisons in a single find() or $match filter.

🧠 How $expr Works

1

MongoDB evaluates the inner expression

For each document, MongoDB runs the aggregation expression inside $expr — comparing fields, computing arithmetic, or checking conditions.

Evaluate
2

Expression returns true or false

Comparison and logical operators produce a boolean result for each document, just like in aggregation $project stages.

Result
3

Matching documents pass the filter

Documents where the expression is true continue through find() or $match. Others are excluded.

Filter
=

Dynamic query results

You get documents matching field-to-field rules that standard query operators alone cannot express.

Conclusion

The $expr operator unlocks the full power of aggregation expressions inside query filters. It is the go-to tool when you need to compare fields on the same document, apply arithmetic in filters, or write dynamic conditions that standard query operators cannot handle.

For beginners, remember: wrap your aggregation expression in { $expr: ... }, use "$field" with a dollar prefix for field references, and reserve $expr for cases where regular query syntax is not enough.

💡 Best Practices

✅ Do

  • Use $expr when comparing two fields on the same document
  • Prefix field names with $ inside the expression
  • Prefer standard query operators when comparing a field to a literal
  • Combine $and and $or for compound conditions
  • Place $expr filters early in pipelines for performance

❌ Don’t

  • Use $expr for simple field-vs-literal comparisons
  • Forget the $ prefix on field references inside expressions
  • Put $expr inside $project (it is a query operator)
  • Overuse $expr when standard query syntax works fine
  • Assume $expr supports every aggregation stage operator

Key Takeaways

Knowledge Unlocked

Five things to remember about $expr

Use these points when writing dynamic MongoDB queries.

5
Core concepts
📝 02

Wrap Syntax

{ $expr: { ... } }

Syntax
🛠 03

Field vs Field

Compare "$a" and "$b".

Usage
🔍 04

Dynamic Filters

Budget, validation rules.

Use case
05

$ Prefix

Fields need "$field".

Edge case

❓ Frequently Asked Questions

$expr lets you use aggregation expression operators inside find() queries and $match stages. It enables comparisons between fields, arithmetic in filters, and dynamic conditions that standard query operators cannot express.
The syntax is { $expr: <aggregation expression> }. Wrap any aggregation expression such as { $gt: [ "$spent", "$budget" ] } or { $eq: [ "$status", "active" ] } inside $expr.
Use $expr when you need to compare two fields on the same document (like spent > budget), perform arithmetic in a filter, or combine multiple aggregation operators in one condition.
Yes. Inside $expr, reference document fields with a $ prefix, like "$spent" or "$budget". This is the aggregation expression syntax, not the standard query field name.
Yes. $expr works inside the $match stage of an aggregation pipeline, using the same syntax as in find() queries.

Continue the Operator Series

Move on to $filter for array filtering, or review $eq for equality comparisons.

Next: $filter →

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.

5 people found this page helpful