Menu

MongoDB $switch: Syntax, Examples, and $cond Comparison

Updated on

MongoDB $switch is an aggregation expression for multi-branch conditional logic. It evaluates branches in order and returns the then expression from the first branch whose case evaluates to true.

Use $switch when a result depends on several conditions. For a simple if/else decision, $cond is usually shorter.

Syntax

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

Important behavior:

  • branches must contain at least one branch.
  • Each branch contains only case and then.
  • MongoDB evaluates branches from top to bottom.
  • The first true branch wins, even if later conditions would also be true.
  • default is optional, but if it is omitted and no branch matches, MongoDB returns an error.

Example: classify scores

Suppose a students collection contains:

{ "_id": 1, "name": "Ana", "score": 92 }
{ "_id": 2, "name": "Ben", "score": 76 }
{ "_id": 3, "name": "Cara", "score": 61 }

Use $switch inside $project to create a grade band:

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"
        }
      }
    }
  }
])

The result is equivalent to:

{ "_id": 1, "name": "Ana",  "score": 92, "grade": "A" }
{ "_id": 2, "name": "Ben",  "score": 76, "grade": "C" }
{ "_id": 3, "name": "Cara", "score": 61, "grade": "D" }

The ordering matters. If the score >= 60 branch appeared first, a score of 92 would match that branch before MongoDB reached score >= 90.

Example: return values from document fields

Both case and then accept aggregation expressions:

db.orders.aggregate([
  {
    $project: {
      total: 1,
      shippingTier: {
        $switch: {
          branches: [
            { case: { $gte: ["$total", 200] }, then: "free-express" },
            { case: { $gte: ["$total", 75] }, then: "free-standard" }
          ],
          default: "paid-standard"
        }
      }
    }
  }
])

$switch vs $cond

Use $cond for one condition with two outcomes:

{
  $cond: [
    { $gte: ["$total", 75] },
    "free-shipping",
    "paid-shipping"
  ]
}

Use $switch when you would otherwise nest several $cond expressions. It is easier to read and makes branch priority explicit.

Common mistakes

Omitting default when no branch is guaranteed to match

This can fail at runtime:

{
  $switch: {
    branches: [
      { case: { $eq: ["$status", "paid"] }, then: 1 }
    ]
  }
}

Add a default unless your data guarantees one branch always matches.

Putting broad conditions before specific conditions

Because the first true branch wins, put the most specific or highest-priority conditions first.

Using $switch as a query filter

$switch is an aggregation expression. Use it inside stages such as $project, $set, or expression contexts. For ordinary document filtering, query operators are usually more direct.

Further reading