MongoDB $switch Operator

Beginner
⏱️ 8 min read
📚 Updated: Jul 2026
🎯 4 Examples
Conditional Logic

What You’ll Learn

The $switch operator evaluates multiple case branches and returns the result from the first match — like a switch/case statement in programming. Use it instead of deeply nested $cond when you have three or more outcomes.

01

Multi-Branch

Many cases at once.

02

Syntax

branches + default.

03

First Match

Top-down order.

04

$project Stage

Label records.

05

Use Cases

Grades, tiers, status.

06

vs $cond

Switch vs if/else.

Definition and Usage

In MongoDB’s aggregation framework, the $switch operator checks an ordered list of case expressions. When a case evaluates to true, MongoDB returns the corresponding then value and stops. If no case matches, it returns the optional default value (or null if omitted).

This is ideal for letter grades, priority tiers, shipping categories, and any scenario where a single field maps to one of several labels based on numeric ranges or equality checks.

💡
Beginner Tip

Put the most specific or highest-priority cases first. MongoDB only uses the first branch that matches — later branches are skipped.

📝 Syntax

The $switch operator uses a branches array and an optional default:

mongosh
{
  $switch: {
    branches: [
      { case: <expression>, then: <expression> },
      { case: <expression>, then: <expression> },
      ...
    ],
    default: <expression>
  }
}

Minimal Example

mongosh
{
  $switch: {
    branches: [
      {
        case: { $gte: [ "$score", 90 ] },
        then: "A"
      },
      {
        case: { $gte: [ "$score", 80 ] },
        then: "B"
      }
    ],
    default: "C"
  }
}

Syntax Rules

  • branches — array of objects, each with case (boolean) and then (result).
  • default — optional fallback when no case matches.
  • Branches are evaluated top to bottom; first true case wins.
  • Each case must evaluate to a boolean (use $gte, $eq, $and, etc.).
  • then and default can be strings, numbers, or nested expressions.
  • Use inside $project, $addFields, $set, or $group.

💡 $switch vs $cond

$cond — one condition, two outcomes (if / else)
$switch — many branches in a flat list (case / case / default)
Three+ outcomes? Prefer $switch over nested $cond for readability.

⚡ Quick Reference

QuestionAnswer
Operator typeAggregation expression operator (conditional)
Syntax{ $switch: { branches: [...], default: ... } }
Evaluation orderTop to bottom; first match wins
default branchOptional; null if omitted and no match
case typeMust evaluate to boolean
Common stages$project, $addFields, $set, $group
Letter grade
{
  $switch: {
    branches: [
      { case: { $gte: ["$s",90] },
        then: "A" },
      ...
    ],
    default: "F"
  }
}

Score tiers

Equality
{
  case: { $eq: ["$status","active"] },
  then: 1
}

Match a value

default
default: "Unknown"

Fallback label

No match
// no default
→ null

Omit default

Examples Gallery

Assign letter grades, map order priorities, label shipping tiers, and compare with nested $cond.

📚 Letter Grades

Map numeric scores to letter grades using ordered case branches.

Sample Input Documents

Suppose you have a students collection with exam scores:

mongosh
[
  { "_id": 1, "name": "Alice", "score": 95 },
  { "_id": 2, "name": "Bob",   "score": 82 },
  { "_id": 3, "name": "Carol", "score": 71 },
  { "_id": 4, "name": "Dave",  "score": 58 }
]

Example 1 — Letter Grades with $switch

Assign A through F based on score thresholds (highest tier first):

mongosh
db.students.aggregate([
  {
    $project: {
      name: 1,
      score: 1,
      grade: {
        $switch: {
          branches: [
            {
              case: { $gte: [ "$score", 90 ] },
              then: "A"
            },
            {
              case: { $gte: [ "$score", 80 ] },
              then: "B"
            },
            {
              case: { $gte: [ "$score", 70 ] },
              then: "C"
            },
            {
              case: { $gte: [ "$score", 60 ] },
              then: "D"
            }
          ],
          default: "F"
        }
      }
    }
  }
])

How It Works

MongoDB checks each branch in order. A score of 95 matches the first branch (>= 90) and returns "A" without checking lower tiers.

📈 Tiers and Status Mapping

Apply $switch to business rules and categorical labels.

Example 2 — Order Priority Tiers

Classify orders by total amount:

mongosh
db.orders.aggregate([
  {
    $project: {
      orderId: 1,
      total: 1,
      priority: {
        $switch: {
          branches: [
            {
              case: { $gte: [ "$total", 1000 ] },
              then: "high"
            },
            {
              case: { $gte: [ "$total", 100 ] },
              then: "medium"
            }
          ],
          default: "low"
        }
      }
    }
  }
])

// total: 1500 → priority: "high"
// total: 250  → priority: "medium"
// total: 45   → priority: "low"

How It Works

Each branch defines a threshold. The default catches everything below the lowest tier.

Example 3 — Status Code to Label

Map numeric status codes to human-readable labels:

mongosh
db.tasks.aggregate([
  {
    $addFields: {
      statusLabel: {
        $switch: {
          branches: [
            {
              case: { $eq: [ "$statusCode", 1 ] },
              then: "Open"
            },
            {
              case: { $eq: [ "$statusCode", 2 ] },
              then: "In Progress"
            },
            {
              case: { $eq: [ "$statusCode", 3 ] },
              then: "Done"
            }
          ],
          default: "Unknown"
        }
      }
    }
  }
])

How It Works

Use $eq in each case for exact value matching. The default branch handles unexpected codes gracefully.

Example 4 — $switch vs Nested $cond

The same grade logic with nested $cond is harder to read:

mongosh
// Nested $cond (works, but verbose)
grade: {
  $cond: [
    { $gte: [ "$score", 90 ] }, "A",
    { $cond: [
      { $gte: [ "$score", 80 ] }, "B",
      { $cond: [
        { $gte: [ "$score", 70 ] }, "C", "F"
      ]}
    ]}
  ]
}

// $switch — same logic, flat and clear
grade: {
  $switch: {
    branches: [
      { case: { $gte: [ "$score", 90 ] }, then: "A" },
      { case: { $gte: [ "$score", 80 ] }, then: "B" },
      { case: { $gte: [ "$score", 70 ] }, then: "C" }
    ],
    default: "F"
  }
}

How It Works

Both approaches produce the same result. Prefer $switch when you have three or more outcomes.

Bonus — Omitting default

When no branch matches and default is omitted, the result is null:

mongosh
{
  $switch: {
    branches: [
      {
        case: { $eq: [ "$type", "premium" ] },
        then: "VIP"
      }
    ]
  }
}

// type: "premium" → "VIP"
// type: "standard" → null

How It Works

Include a default branch when you always need a fallback value.

🚀 Use Cases

  • Grading and scoring — map numeric scores to letter grades or performance bands.
  • Priority classification — tier customers, orders, or tickets by amount or urgency.
  • Status labeling — convert codes or enums to display-friendly strings.
  • Shipping and pricing — assign categories based on weight, distance, or order value.

🧠 How $switch Works

1

MongoDB reads the branches array

Each branch has a case (condition) and a then (result).

Input
2

Cases are tested top to bottom

The first branch whose case evaluates to true wins. Remaining branches are skipped.

Evaluate
3

The then value is returned

If no case matches, MongoDB returns default (or null).

Output
=

Multi-way label assigned

Use in $project or $addFields to enrich documents.

Conclusion

The $switch operator simplifies multi-branch conditional logic in MongoDB aggregation pipelines. It replaces hard-to-read nested $cond chains with a flat list of cases and an optional default.

Order branches from most specific to least specific, and always include a default when you need a guaranteed fallback. Next in the series: $tan.

💡 Best Practices

✅ Do

  • Use $switch when you have three or more possible outcomes
  • Order branches from highest threshold to lowest (for range checks)
  • Include a default branch for unexpected values
  • Build case expressions with $gte, $eq, or $and
  • Keep each branch focused on one clear condition

❌ Don’t

  • Put lower thresholds before higher ones in range-based grading
  • Forget that only the first matching branch runs
  • Use non-boolean expressions in case fields
  • Nested $cond deeply when $switch would be clearer
  • Assume default is required — omitting it returns null

Key Takeaways

Knowledge Unlocked

Five things to remember about $switch

Use these points when building multi-way conditionals.

5
Core concepts
📝 02

branches[]

case + then.

Syntax
🔢 03

First match

Top-down.

Rule
🛠 04

default

Fallback value.

Optional
05

vs $cond

Flat vs nested.

Compare

❓ Frequently Asked Questions

$switch evaluates an ordered list of case branches and returns the then value from the first branch whose case expression is true. If no branch matches, it returns the default value (or null if default is omitted).
The syntax is { $switch: { branches: [ { case: <expression>, then: <expression> }, ... ], default: <expression> } }. Branches are checked top to bottom; only the first match wins.
$cond handles one if-then-else decision. $switch handles many branches in one expression — like a switch/case statement. Use $switch instead of deeply nested $cond for readability.
No. default is optional. If you omit it and no case matches, $switch returns null.
Inside expression stages such as $project, $addFields, $set, and $group accumulators whenever you need multi-way conditional logic.

Continue the Operator Series

Move on to $tan for tangent calculations, or review $cond for simple if-then-else logic.

Next: $tan →

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