Skip to content

DOCS-9337: $switch aggregation operator #2780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions source/includes/ref-toc-aggregation-conditional.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ description: |
null result. Null result encompasses instances of undefined values or
missing fields. Accepts two expressions as arguments. The result of
the second expression can be null.
---
name: :expression:`$switch`
file: /reference/operator/aggregation/switch
description: |
Evaluates a series of case expressions. When it finds an expression
which evaluates to ``true``, ``$switch`` executes a specified
expression and breaks out of the control flow.
...
2 changes: 2 additions & 0 deletions source/reference/operator/aggregation/and.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Definition
For more information on expressions, see
:ref:`aggregation-expressions`.

.. _and-boolean-behavior:

Behavior
--------

Expand Down
203 changes: 203 additions & 0 deletions source/reference/operator/aggregation/switch.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
=====================
$switch (aggregation)
=====================

.. default-domain:: mongodb

.. contents:: On this page
:local:
:backlinks: none
:depth: 1
:class: singlecol

Definition
----------

.. expression:: $switch

.. versionadded:: 3.4

Evaluates a series of case expressions. When it finds an expression
which evaluates to ``true``, ``$switch`` executes a specified
expression and breaks out of the control flow.

:expression:`$switch` has the following syntax:

.. code-block:: javascript

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

The objects in the ``branches`` array must contain only a ``case``
field and a ``then`` field.

.. list-table::
:header-rows: 1
:widths: 30 65

* - Operand
- Description

* - ``branches``

- An array of control branch documents. Each branch is a
document with the following fields:

- ``case``
Can be any valid :ref:`expression
<aggregation-expressions>` that resolves to a
``boolean``. If the result is not a ``boolean``, it is
coerced to a boolean value. More information about how
MongoDB evaluates expressions as either true or false
can be found :ref:`here<and-boolean-behavior>`.

- ``then``
Can be any valid :ref:`expression
<aggregation-expressions>`.

The ``branches`` array must contain at least one branch
document.

* - ``default``

- Optional. The path to take if no branch ``case`` expression
evaluates to ``true``.

Although optional, if ``default`` is unspecified and no
branch ``case`` evaluates to true, :expression:`$switch`
returns an error.

Behavior
--------

The various case statements do not need to be mutually exclusive.
:expression:`$switch` executes the first branch it finds which
evaluates to ``true``. If none of the branches evaluates to true,
:expression:`$switch` executes the ``default`` option.

The following conditions cause :expression:`$switch` to fail with an
error:

- The ``branches`` field is missing or is not an array with at least
one entry.

- An object in the ``branches`` array does not contain a ``case``
field.

- An object in the ``branches`` array does not contain a ``then``
field.

- An object in the ``branches`` array contains a field other than
``case`` or ``then``.

- No ``default`` is specified and no ``case`` evaluates to ``true``.

.. list-table::
:header-rows: 1
:widths: 80 20

* - Example
- Results

* - .. code-block:: javascript

{
$switch: {
branches: [
{ case: { $eq: [ 0, 5 ] }, then: "equals" },
{ case: { $gt: [ 0, 5 ] }, then: "greater than" },
{ case: { $lt: [ 0, 5 ] }, then: "less than" }
]
}
}

- ``"less than"``

* - .. code-block:: javascript

{
$switch: {
branches: [
{ case: { $eq: [ 0, 5 ] }, then: "equals" },
{ case: { $gt: [ 0, 5 ] }, then: "greater than" }
],
default: "Did not match"
}
}

- ``"Did not match"``

* - .. code-block:: javascript

{
$switch: {
branches: [
{ case: "this is true", then: "first case" },
{ case: false, then: "second case" }
],
default: "Did not match"
}
}

- ``"First case"``

Example
-------

A collection named ``grades`` contains the following documents:

.. code-block:: javascript

{ "_id" : 1, "name" : "Susan Wilkes", "scores" : [ 87, 86, 78 ] }
{ "_id" : 2, "name" : "Bob Hanna", "scores" : [ 71, 64, 81 ] }
{ "_id" : 3, "name" : "James Torrelio", "scores" : [ 91, 84, 97 ] }

The following aggregation operation uses :expression:`$switch` to
display a particular message based on each student's average score.

.. code-block:: javascript

db.grades.aggregate( [
{
$project:
{
"name" : 1,
"summary" :
{
$switch:
{
branches: [
{
case: { $gte : [ { $avg : "$scores" }, 90 ] },
then: "Doing great!"
},
{
case: { $and : [ { $gte : [ { $avg : "$scores" }, 80 ] },
{ $lt : [ { $avg : "$scores" }, 90 ] } ] },
then: "Doing pretty well."
},
{
case: { $lt : [ { $avg : "$scores" }, 80 ] },
then: "Needs improvement."
}
],
default: "No scores found."
}
}
}
}
] )

The operation returns the following:

.. code-block:: javascript

{ "_id" : 1, "name" : "Susan Wilkes", "summary" : "Doing pretty well." }
{ "_id" : 2, "name" : "Bob Hanna", "summary" : "Needs improvement." }
{ "_id" : 3, "name" : "James Torrelio", "summary" : "Doing great!" }