Home > Blockchain >  Simplifying MongoDB aggregation $project stage
Simplifying MongoDB aggregation $project stage

Time:12-06

I have the following working $project stage in my MongoDB aggregation pipeline. The issue is that I am not fully happy with it and would like to hear your suggestions on how the stage could be improved:

$project: {
    _id: 0,
    name: 1,
    points: 1,
    level: {
        $cond: {
            if: { $gt: [ "$points", 250 ] },
            then: {
                $cond: {
                    if: { $gt: [ "$points", 500 ] },
                    then: {
                        $cond: {
                            if: { $gt: [ "$points", 3000 ] },
                            then: {
                                $cond: {
                                    if: { $gt: [ "$points", 5000 ] },
                                    then: {
                                        $cond: {
                                            if: { $gt: [ "$points", 20000 ] },
                                            then: 6,
                                            else: 5
                                        }
                                    },
                                    else: 4
                                }
                            },
                            else: 3
                        }
                    },
                    else: 2
                }
            },
            else: 1
        }
    }
}

Basically, what the project stage does is compute a certain level (1-6), based on achieved points. Right now it looks really hard to read and error prone, any suggestions on how to improve would be welcome.

CodePudding user response:

One option is to use $switch:

db.collection.aggregate([
  {$project: {
      _id: 0,
      name: 1,
      points: 1,
      level: {
        $switch: {
          branches: [
            {
              case: {$lte: ["$points", 250]},
              then: 1
            },
            {
              case: {$and: [{$gt: ["$points", 250]}, {$lt: ["$points", 500]}]}, 
              then: 2
            },
            {
              case: {$and: [{$gt: ["$points", 500]}, {$lt: ["$points", 3000]}]}, 
              then: 3
            },
          ],
          default: 4
        }
      }
    }
  }
])

See how it works on the playground example, although it looks like repeating the lower bound is redundent.

  • Related