MongoDB - Are there any `$bucket` aggregation operator alternatives for Amazon DocumentDB?

Having migrated to Amazon DocumentDB, I suppose I am in in dire straits as it does not support $bucket stage operator, as mentioned in Amazon DocumentDB - Supported MongoDB APIs, Operations, and Data Types.

– Data –

This is raw data, one can insert it in MongoDB :

[{
  "_id": {
    "$oid": "6447544a4e512379dee1ced4"
  },
  "name": "Mike Trout",
  "uniformNumber": 27,
  "team": "Los Angeles Angels",
  "date": "2023/02",
  "totalHomeruns": 333
},{
  "_id": {
    "$oid": "644755b54e512379dee1ced5"
  },
  "name": "Shohei Ohtani",
  "uniformNumber": 17,
  "team": "Los Angeles Angels",
  "date": "2023/03",
  "totalHomeruns": 337
},{
  "_id": {
    "$oid": "644755b54e512379dee1ced6"
  },
  "name": "Aaron Judge",
  "uniformNumber": 99,
  "team": "New York Yankees",
  "date": "2023/01",
  "totalHomeruns": 295
},{
  "_id": {
    "$oid": "644755b54e512379dee1ced7"
  },
  "name": "Mookie Betts",
  "uniformNumber": 11,
  "team": "Los Angeles Dodgers",
  "date": "2023/01",
  "totalHomeruns": 251
},{
  "_id": {
    "$oid": "644755b54e512379dee1ced8"
  },
  "name": "Bryce Harper",
  "uniformNumber": 25,
  "team": "Philadelphia Phillies",
  "date": "2023/02",
  "totalHomeruns": 217
},{
  "_id": {
    "$oid": "644755b54e512379dee1ced9"
  },
  "name": "Ronald Acuna Jr.",
  "uniformNumber": 23,
  "team": "Atlanta Braves",
  "date": "2023/02",
  "totalHomeruns": 229
},{
  "_id": {
    "$oid": "644755b54e512379dee1cee1"
  },
  "name": "Marcus Semien",
  "uniformNumber": 19,
  "team": "Texas Rangers",
  "date": "2023/03",
  "totalHomeruns": 196
},{
  "_id": {
    "$oid": "644755b54e512379dee1cee2"
  },
  "name": "Vladimir Guerrero Jr.",
  "uniformNumber": 6,
  "team": "Toronto Blue Jays",
  "date": "2023/03",
  "totalHomeruns": 188
},{
  "_id": {
    "$oid": "644755b54e512379dee1cee3"
  },
  "name": "Yordan Alvarez",
  "uniformNumber": 10,
  "team": "Houston Astros",
  "date": "2023/02",
  "totalHomeruns": 137
},{
  "_id": {
    "$oid": "644755b54e512379dee1cee4"
  },
  "name": "Andrew Benintendi",
  "uniformNumber": 23,
  "team": "Chicago Whitesox",
  "date": "2023/02",
  "totalHomeruns": 116
},{
  "_id": {
    "$oid": "644755b54e512379dee1cee5"
  },
  "name": "Wander Franco",
  "uniformNumber": 33,
  "team": "Tampa Bay Rays",
  "date": "2023/02",
  "totalHomeruns": 97
}]

– Aggregation –

The $bucket stage looks like this :

{
  groupBy: '$totalHomeruns',
  boundaries: [
    0, 95, 105,115,125,135,145,155,165,175,185,195,
    205,215,225,235,245,255,265,275,285,295,
    305,315,325,335,345,355,365,375,385,395,405,
  ],
  default: 'Other',
  output: {
    count: {
      $sum: 1,
    },
    playerData: {
      $push: {
        name: '$name',
        uniformNumber: '$uniformNumber',
        team: '$team',
        totalHomeruns: '$totalHomeruns',
        date: '$date'
      },
    },
  },
}

– Expected Result –

This is what $bucket stage above produces :

[
  {
    _id: 95,
    count: 1,
    playerData: [
      {
        name: 'Wander Franco',
        uniformNumber: 33,
        team: 'Tampa Bay Rays',
        totalHomeruns: 97,
        date: '2023/02',
      },
    ],
  },
  {
    _id: 115,
    count: 1,
    playerData: [
      {
        name: 'Andrew Benintendi',
        uniformNumber: 23,
        team: 'Chicago Whitesox',
        totalHomeruns: 116,
        date: '2023/02',
      },
    ],
  },

  ...
  
  {
    _id: 335,
    count: 1,
    playerData: [
      {
        name: 'Shohei Ohtani',
        uniformNumber: 17,
        team: 'Los Angeles Angels',
        totalHomeruns: 337,
        date: '2023/03',
      },
    ],
  }
]

– Question –

Is it possible to get the expected output above without $bucket stage operator?

Thank you in advance!

Fortunately, $group operation did the trick :

{
  _id: {
    $switch: {
      branches: [
        { case: { $lt: [ "$totalHomeruns", 95] }, then: 0 },
        { case: { $lt: [ "$totalHomeruns", 105] }, then: 95 },
        { case: { $lt: [ "$totalHomeruns", 115] }, then: 105 },
        { case: { $lt: [ "$totalHomeruns", 125] }, then: 115 },
        { case: { $lt: [ "$totalHomeruns", 135] }, then: 125 },
        { case: { $lt: [ "$totalHomeruns", 145] }, then: 135 },
        { case: { $lt: [ "$totalHomeruns", 155] }, then: 145 },
        { case: { $lt: [ "$totalHomeruns", 165] }, then: 155 },
        { case: { $lt: [ "$totalHomeruns", 175] }, then: 165 },
        { case: { $lt: [ "$totalHomeruns", 185] }, then: 175 },
        { case: { $lt: [ "$totalHomeruns", 195] }, then: 185 },
        { case: { $lt: [ "$totalHomeruns", 205] }, then: 195 },
        { case: { $lt: [ "$totalHomeruns", 215] }, then: 205 },
        { case: { $lt: [ "$totalHomeruns", 225] }, then: 215 },
        { case: { $lt: [ "$totalHomeruns", 235] }, then: 225 },
        { case: { $lt: [ "$totalHomeruns", 245] }, then: 235 },
        { case: { $lt: [ "$totalHomeruns", 255] }, then: 245 },
        { case: { $lt: [ "$totalHomeruns", 265] }, then: 255 },
        { case: { $lt: [ "$totalHomeruns", 275] }, then: 265 },
        { case: { $lt: [ "$totalHomeruns", 285] }, then: 275 },
        { case: { $lt: [ "$totalHomeruns", 295] }, then: 285 },
        { case: { $lt: [ "$totalHomeruns", 305] }, then: 295 },
        { case: { $lt: [ "$totalHomeruns", 315] }, then: 305 },
        { case: { $lt: [ "$totalHomeruns", 325] }, then: 315 },
        { case: { $lt: [ "$totalHomeruns", 335] }, then: 325 },
        { case: { $lt: [ "$totalHomeruns", 345] }, then: 335 },
        { case: { $lt: [ "$totalHomeruns", 355] }, then: 345 },
        { case: { $lt: [ "$totalHomeruns", 365] }, then: 355 },
        { case: { $lt: [ "$totalHomeruns", 375] }, then: 365 },
        { case: { $lt: [ "$totalHomeruns", 385] }, then: 375 },
        { case: { $lt: [ "$totalHomeruns", 395] }, then: 385 },
        { case: { $lt: [ "$totalHomeruns", 405] }, then: 395 },
        { case: { $lt: [ "$totalHomeruns", 415] }, then: 405 },
        { case: { $lt: [ "$totalHomeruns", 425] }, then: 415 },
        { case: { $lt: [ "$totalHomeruns", 435] }, then: 425 },
        { case: { $lt: [ "$totalHomeruns", 445] }, then: 435 },
        { case: { $lt: [ "$totalHomeruns", 455] }, then: 445 },
        { case: { $lt: [ "$totalHomeruns", 465] }, then: 455 },
        { case: { $lt: [ "$totalHomeruns", 475] }, then: 465 },
        { case: { $lt: [ "$totalHomeruns", 485] }, then: 475 },
        { case: { $lt: [ "$totalHomeruns", 495] }, then: 485 },
        { case: { $lt: [ "$totalHomeruns", 505] }, then: 495 },
      ],
      default: "Other"
    }
  },
  count: { $sum: 1 },
  playerData: {
    $push: {
      name: "$name",
      uniformNumber: "$uniformNumber",
      team: "$team",
      totalHomeruns: "$totalHomeruns",
      date: "$date"
    }
  }
}

However, the output above does not get sorted based on _id like $bucket’s.
Therefore, $sort comes in to play :

{
  _id: 1
}

To have a look at entire aggregation, please have a look at MongoDB Playground - $bucket alternative.

– Result –

[
  {
    "_id": 95,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Wander Franco",
        "team": "Tampa Bay Rays",
        "totalHomeruns": 97,
        "uniformNumber": 33
      }
    ]
  },
  {
    "_id": 115,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Andrew Benintendi",
        "team": "Chicago Whitesox",
        "totalHomeruns": 116,
        "uniformNumber": 23
      }
    ]
  },
  {
    "_id": 135,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Yordan Alvarez",
        "team": "Houston Astros",
        "totalHomeruns": 137,
        "uniformNumber": 10
      }
    ]
  },
  {
    "_id": 185,
    "count": 1,
    "playerData": [
      {
        "date": "2023/03",
        "name": "Vladimir Guerrero Jr.",
        "team": "Toronto Blue Jays",
        "totalHomeruns": 188,
        "uniformNumber": 6
      }
    ]
  },
  {
    "_id": 195,
    "count": 1,
    "playerData": [
      {
        "date": "2023/03",
        "name": "Marcus Semien",
        "team": "Texas Rangers",
        "totalHomeruns": 196,
        "uniformNumber": 19
      }
    ]
  },
  {
    "_id": 215,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Bryce Harper",
        "team": "Philadelphia Phillies",
        "totalHomeruns": 217,
        "uniformNumber": 25
      }
    ]
  },
  {
    "_id": 225,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Ronald Acuna Jr.",
        "team": "Atlanta Braves",
        "totalHomeruns": 229,
        "uniformNumber": 23
      }
    ]
  },
  {
    "_id": 245,
    "count": 1,
    "playerData": [
      {
        "date": "2023/01",
        "name": "Mookie Betts",
        "team": "Los Angeles Dodgers",
        "totalHomeruns": 251,
        "uniformNumber": 11
      }
    ]
  },
  {
    "_id": 295,
    "count": 1,
    "playerData": [
      {
        "date": "2023/01",
        "name": "Aaron Judge",
        "team": "New York Yankees",
        "totalHomeruns": 295,
        "uniformNumber": 99
      }
    ]
  },
  {
    "_id": 325,
    "count": 1,
    "playerData": [
      {
        "date": "2023/02",
        "name": "Mike Trout",
        "team": "Los Angeles Angels",
        "totalHomeruns": 333,
        "uniformNumber": 27
      }
    ]
  },
  {
    "_id": 335,
    "count": 1,
    "playerData": [
      {
        "date": "2023/03",
        "name": "Shohei Ohtani",
        "team": "Los Angeles Angels",
        "totalHomeruns": 337,
        "uniformNumber": 17
      }
    ]
  }
]

This might not be the best answer but better than crying over spilled milk xD