Home > Mobile >  Mongodb group by players
Mongodb group by players

Time:11-22

I have a API that saves gameplay data in a mongodb. that accepts gameID, userID and score

{
  "gameId": "G1",
  "userId": "U22",
  "score": 420
},
{
  "gameId": "G2",
  "userId": "U22",
  "score": 10
},
{
  "gameId": "G1",
  "userId": "U22",
  "score": 80
},
{
  "gameId": "G1",
  "userId": "U25",
  "score": 400
}

when 'Game Over' game score document creates. so users can play many times in a same day.

now I can get game leaderboard like below.

db.plays.aggrigate([
 {
  _id: '$userId',
  played: {
    $sum:1
  },
  score:{
    $sum: '$score'
  }
},
{
    $limit: 100
}, {
    $sort: {
        score: -1
    }
}
]);

output

{
    _id: U22,
    played:3,
    score:510
},
{
    _id: U25,
    played:1,
    score:100
}

now I wanna get array of played games.

{
    _id: U22,
    played:[
        {
            gameId: G1,
            score: 500
        },
        {
            gameId: G2,
            score: 10
        }
    ],
    score:500
},
{
    _id: U25,
    played:[
        {
            gameId: G1,
            score: 400
        }
    ],
    score:100
},

how can I achieve this. thanks in advance.

CodePudding user response:

One option is to group twice, first by both userId and gameId and then just by userId:

db.collection.aggregate([
  {$group: {
      _id: {game: "$gameId", user: "$userId"},
      score: {$sum: "$score"}
  }},
  {$group: {
      _id: "$_id.user",
      played: {$push: {game: "$_id.game", score: "$score"}},
      score: {$max: "$score"}
  }},
  {$sort: {score: -1}},
  {$limit: 100}
])

See how it works on the playground example

  • Related