Search code examples
databasemongodbnosqlaggregation-frameworkaggregate

How to get sum of specific number of nested objects in an array sorted by date with aggregation pipeline, MongoDB


I need to get the sum of the "points" of the 3 most recent entries/objects under members array based on date. So, the total points should be 3000. (Person B 500, Person C 1000, and Person D 1500).

How do I do that with my current aggregation pipeline? Do I use slice or something?

Here's the document

[{
  "_id": { "$oid": "00001" },
  "leaderId": 001,
  "leader": "Josh",
  "members": [
    {
      "name": "Person A",
      "points": 500,
      "date": 2023-05-30T18:00:00.000+00:00
    },
    {
      "name": "Person B",
      "points": 500,
      "date": 2023-05-30T19:10:00.000+00:00
    },
    {
      "name": "Person C",
      "points": 1000,
      "date": 2023-05-30T19:20:00.000+00:00
    },
    {
      "name": "Person D",
      "points": 1500,
      "date": 2023-05-30T19:30:00.000+00:00
    }]
  }]

Here's my aggregation pipeline that returns 3500 because it gets the sum of points from all objects under members array.

db.users.aggregate([{ $match: { leader: "Josh" } },
{$unwind: "$members"},
{$sort: {"members.date": -1}},
{$group: {_id: "$leaderId", latestThreePoints: {$sum: "$members.points"}}}])

Solution

  • From your current work, you just need an extra $limit stage after the $sort

    db.collection.aggregate([
      {
        $match: {
          leader: "Josh"
        }
      },
      {
        $unwind: "$members"
      },
      {
        $sort: {
          "members.date": -1
        }
      },
      {
        $limit: 3
      },
      {
        $group: {
          _id: "$leaderId",
          latestThreePoints: {
            $sum: "$members.points"
          }
        }
      }
    ])
    

    Mongo Playground