querydrill

Learn ›Advanced aggregation ›Array and conditional expressions

$cond: if / else in a pipeline

$cond$eq$group$gte$project$sum

$cond is a ternary: a condition, a value if true, a value if false. On its own it is small; combined with $sum it produces the conditional counting pattern that turns one pass over a collection into several answers.

In JavaScript:

condition ? A : B

Example:

{
  $project: {
    statusLabel: {
      $cond: {
        if: {
          $gte: [
            "$amount",
            1000
          ]
        },

        then: "high-value",

        else: "normal"
      }
    }
  }
}

Result:

amount >= 1000
        ↓
"high-value"

otherwise
        ↓
"normal"

Very Common Pattern: Conditional Counting

Suppose:

Count completed and pending orders per user.

{
  $group: {
    _id: "$userId",

    completed: {
      $sum: {
        $cond: [
          {
            $eq: [
              "$status",
              "completed"
            ]
          },
          1,
          0
        ]
      }
    },

    pending: {
      $sum: {
        $cond: [
          {
            $eq: [
              "$status",
              "pending"
            ]
          },
          1,
          0
        ]
      }
    }
  }
}

Think:

completed += status === "completed" ? 1 : 0

This is a very useful interview pattern.

Try it

db.products.aggregate([
  {
    $project: {
      _id: 0,
      product: 1,
      price: 1,
      tier: {
        $cond: {
          if: { $gte: ["$price", 250] },
          then: "high-value",
          else: "normal"
        }
      }
    }
  },
  { $limit: 6 }
])

Move the threshold and the labels move with it. No branch ran in your application - the database returned the label.

Practise this

1 exercise