Home > Software design >  How to get X students from each grade in MongoDB version 5.0?
How to get X students from each grade in MongoDB version 5.0?

Time:08-21

I have a mongoDB collection named students with the fields grade and name.

I would like to create a query that will get up to 2 students from each grade inside my gradesList.

In version MongoDB version 5.2. and above, you can use the $firstN aggregation operator together with $group like this:

const gradesList = [10, 11, 12]

db.students.aggregate([ { $match: { grade: { $in: gradesList } } },
  {
    $group: {
      _id: '$grade',
      name: {
        $firstN: {
          n: 2,
          input: "$name"
        }
      }
    }
  },
  { $unwind: "$name" },
  { $project: { _id: 0, name: 1, grade: "$_id" } },
])

And this is the output:

[
    {
        name: 'Albert',
        grade: 10
    },
    {
        name: 'Tim',
        grade: 10
    },
    {
        name: 'Monika',
        grade: 11
    },
    {
        name: 'Mike',
        grade: 11
    },
    {
        name: 'Rich',
        grade: 12
    },
    {
        name: 'Beth',
        grade: 12
    },
]

However, in order to use $firstN alongside MongoDB Atlas, you need to use a dedicated cluster which starts at around $60 a month, because the shared cluster tiers only support mongodb version 5.0, which don't support $firstN.

Is there a way to accomplish the same objective with aggregation operators available in version 5.0?

CodePudding user response:

Only a small change is needed to be compatible with MongoDB version 5.0.

db.collection.aggregate([
  {
    "$match": {
      "grade": {"$in": [10, 11, 12]}
    }
  },
  {
    "$group": {
      "_id": "$grade",
      "name": {"$push": "$name"}
    }
  },
  {
    "$set": {
      "name": {"$slice": ["$name", 2]}
    }
  },
  {"$unwind": "$name"},
  {
    "$project": {
      "_id": 0,
      "name": 1,
      "grade": "$_id"
    }
  },
  {
    "$sort": {
      "grade": 1,
      "name": 1
    }
  }
])

Try it on mongoplayground.net.

  • Related