Details

      Description

      Syntax

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

      Examples

      > db.coll.insert([
        {_id: 0, x: 0}
        {_id: 1, x: -1}
        {_id: 2, x: 2}
      ]);
      > db.coll.aggregate([{
        $project: {
          z: {
            $switch: {
              branches: [
                {
                  case: {$eq: ["$x", 0]},
                  then: "Equal to zero."
                },
                {
                  case: {$eq: [{$abs: "$x"}, 1]},
                  then: "Equal to plus or minus one."
                },
              ],
              default: "Something else."
            }
          }
        }
      }])
      {_id: 0, z: "Equal to zero."}
      {_id: 1, z: "Equal to plus or minus one."}
      {_id: 2, z: "Something else."}

      Notes

      • Allows $project expressions to be written without convoluted $conds.
      • If "case" does not return a boolean, the value will be coerced to a bool.
      • Since each case does not have to be mutually exclusive, an input will enter the first branch it matches.
        Errors
      • 'branches' is missing or not an array with at least one entry.
      • An entry in 'branches' does not contain 'case'
      • An entry in 'branches' does not contain 'then'
      • If 'default' is not specified, and an input doesn't match, an error will be thrown.

      Old Description:
      Currently if you want to do a multi-way switch statement equivalent in $project you have to do a very messy embedded sequence of {$cond:[]} statements (emulating an if-elif-elif-elif type sequence) which is very unreadable.

      It would be nice to have an operator to do something like:

       'field: {$case:[ {condition1: val1}, {cond2: val2}, etc]}' 

      where the first condition that matches sets the value of field to appropriate val.

      Asya

        Issue Links

          Activity

          Hide
          jcole@solidearth.com John Cole added a comment -

          I'll second the need for this here. We were able to use $concat and a series of $cond to replicate a case statement but it's limited to returning strings.

          Adding a $case as described would greatly improve the readability of agg queries that require strict grouping parameters, a common issue in reports.

          Show
          jcole@solidearth.com John Cole added a comment - I'll second the need for this here. We were able to use $concat and a series of $cond to replicate a case statement but it's limited to returning strings. Adding a $case as described would greatly improve the readability of agg queries that require strict grouping parameters, a common issue in reports.
          Hide
          mullanaphy John Mullanaphy added a comment - - edited

          Going to also add in a vote. Had to make an adhoc $cond to do a fake join to do sorting by name. The solution(s): One table had ids, other table had dynamically changed names associated with the ids, so had to make the aggregate query in code with $cond matching ids to names and then sorting. That had ended up hitting a hash key nesting limit, so then the next solution was to make a:

          {
              "field": {
                  "$add": [
                      {"$cond": [{"$eq":["$name_id","name1"]}, 1, 4]}
                      {"$cond": [{"$eq":["$name_id","name1"]}, 2, 4]}
                      {"$cond": [{"$eq":["$name_id","name1"]}, 3, 4]}
                  ]
              }
          }

          Which also hits limits if you have large numbers of names for ids. Still, switch/case isn't the solution to our problem but while trying to find solutions we realized it would have been a nice alternative to our original nested conditionals. 2.6, will need to check out the $map/$let commands.

          Show
          mullanaphy John Mullanaphy added a comment - - edited Going to also add in a vote. Had to make an adhoc $cond to do a fake join to do sorting by name. The solution(s): One table had ids, other table had dynamically changed names associated with the ids, so had to make the aggregate query in code with $cond matching ids to names and then sorting. That had ended up hitting a hash key nesting limit, so then the next solution was to make a: { "field": { "$add": [ {"$cond": [{"$eq":["$name_id","name1"]}, 1, 4]} {"$cond": [{"$eq":["$name_id","name1"]}, 2, 4]} {"$cond": [{"$eq":["$name_id","name1"]}, 3, 4]} ] } } Which also hits limits if you have large numbers of names for ids. Still, switch/case isn't the solution to our problem but while trying to find solutions we realized it would have been a nice alternative to our original nested conditionals. 2.6, will need to check out the $map/$let commands.
          Hide
          xgen-internal-githook Githook User added a comment -

          Author:

          {u'username': u'benjaminmurphy', u'name': u'Benjamin Murphy', u'email': u'benjamin_murphy@me.com'}

          Message: SERVER-10689 Aggregation now supports the switch expression.
          Branch: master
          https://github.com/mongodb/mongo/commit/77aaa5419340185ad1744f0b25f8543c6add2abc

          Show
          xgen-internal-githook Githook User added a comment - Author: {u'username': u'benjaminmurphy', u'name': u'Benjamin Murphy', u'email': u'benjamin_murphy@me.com'} Message: SERVER-10689 Aggregation now supports the switch expression. Branch: master https://github.com/mongodb/mongo/commit/77aaa5419340185ad1744f0b25f8543c6add2abc
          Hide
          benjamin.murphy Benjamin Murphy (Inactive) added a comment -

          This ticket introduced the $switch expression to aggregation, which must be documented and supported by drivers.

          Show
          benjamin.murphy Benjamin Murphy (Inactive) added a comment - This ticket introduced the $switch expression to aggregation, which must be documented and supported by drivers.

            People

            • Votes:
              7 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                  Agile