Skip to content

Aggregation Expressions

Conditional Expressions

$cond, $ifNull and $switch for branching inside a pipeline.

IntermediateAbout 6 minutes

$match drops documents. `$cond` keeps the document and picks a value. Labels, defaults, and conditional totals all live here — not in a second query from Node.

db.products.aggregate([
  {
    $set: {
      band: {
        $cond: { if: { $gte: ["$price", 4000] }, then: "premium", else: "standard" }
      }
    }
  }
])

// same: { $cond: [{ $gte: ["$price", 4000] }, "premium", "standard"] }
Object form and array form are the same $cond
{ name: "Mechanical Keyboard", price: 4500, band: "premium" }
{ name: "USB-C Cable", price: 200, band: "standard" }
{ $ifNull: ["$discount", 0] }

{
  $switch: {
    branches: [
      { case: { $eq: ["$status", "cancelled"] }, then: 0 },
      { case: { $eq: ["$status", "pending"] }, then: "$amount" }
    ],
    default: "$amount"
  }
}
$ifNull — missing or null becomes 0. $switch — more than two branches.
db.orders.aggregate([
  {
    $group: {
      _id: "$userId",
      paid: {
        $sum: {
          $cond: [{ $ne: ["$status", "cancelled"] }, "$amount", 0]
        }
      }
    }
  }
])
The interview pattern: conditional $sum

$ifNull treats missing and null as the default. A real 0 is kept. Nested $cond works; $switch is what you write when the fourth branch appears. $eq / $gte here are expressions (array operands), not { status: "cancelled" } query syntax — that filter form does not work inside $cond.

Interview question

When do you use $cond instead of $match?

Think about it first.