MongoDB $switch

In MongoDB, the $switch aggregation pipeline operator evaluates a series of case expressions, and executes a specified expression only when a case expression evaluates to true.

Syntax

The syntax goes like this:

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

Example

Suppose we have a collection called pets with the following documents:

{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
{ "_id" : 5, "name" : "Bruce", "type" : "Kangaroo", "weight" : 100 }
{ "_id" : 6, "name" : "Hop", "type" : "Kangaroo", "weight" : 130 }
{ "_id" : 7, "name" : "Punch", "type" : "Kangaroo", "weight" : 200 }
{ "_id" : 8, "name" : "Snap", "type" : "Cat", "weight" : 12 }
{ "_id" : 9, "name" : "Ruff", "type" : "Dog", "weight" : 30 }

We can use the $switch operator to run some case expressions against the weight field:

db.pets.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          weight: 1,
          result: {
            $switch: {
              branches: [
                  { case: { $gt: [ "$weight", 100 ]  }, then: "Heavy" },
                  { case: { $lt: [ "$weight", 20 ]  }, then: "Light" }
              ],
              default: "Medium"
            }
          }
        }
    }
  ]
)

Result:

{ "weight" : 20, "result" : "Medium" }
{ "weight" : 10, "result" : "Light" }
{ "weight" : 7, "result" : "Light" }
{ "weight" : 8, "result" : "Light" }
{ "weight" : 100, "result" : "Medium" }
{ "weight" : 130, "result" : "Heavy" }
{ "weight" : 200, "result" : "Heavy" }
{ "weight" : 12, "result" : "Light" }
{ "weight" : 30, "result" : "Medium" }

Omitting the Default Expression

Omitting the default from the code can result in an error. But this depends on the outcome of the case expressions.

If we remove the default part from the above example, we get an error:

db.pets.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          weight: 1,
          result: {
            $switch: {
              branches: [
                  { case: { $gt: [ "$weight", 100 ]  }, then: "Heavy" },
                  { case: { $lt: [ "$weight", 20 ]  }, then: "Light" }
              ]
            }
          }
        }
    }
  ]
)

Result:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$switch could not find a matching branch for an input, and no default was specified.",
	"code" : 40066,
	"codeName" : "Location40066"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1

In this case, there were input values that weren’t covered by the case expressions (i.e. those between 20 and 100), and so $switch returned an error.

However, if we change the case expressions slightly, we can remove the default part without error:

db.pets.aggregate(
  [
    {
      $project:
        { 
          _id: 0,
          weight: 1,
          result: {
            $switch: {
              branches: [
                  { case: { $gt: [ "$weight", 100 ]  }, then: "Heavy" },
                  { case: { $lte: [ "$weight", 100 ]  }, then: "Light" }
              ]
            }
          }
        }
    }
  ]
)

Result:

{ "weight" : 20, "result" : "Light" }
{ "weight" : 10, "result" : "Light" }
{ "weight" : 7, "result" : "Light" }
{ "weight" : 8, "result" : "Light" }
{ "weight" : 100, "result" : "Light" }
{ "weight" : 130, "result" : "Heavy" }
{ "weight" : 200, "result" : "Heavy" }
{ "weight" : 12, "result" : "Light" }
{ "weight" : 30, "result" : "Light" }

In this example, all documents satisfied all case expressions, and so the default wasn’t needed – which meant that no error was produced.

MongoDB Documentation

See the MongoDB documentation for more detail and examples.