2

I am trying to get an average number of an key in a nested array inside a document, but not sure how to accomplish this.

Here is how my document looks like:

{
  "_id": {
    "$oid": "XXXXXXXXXXXXXXXXX"
  },
  "data": {
    "type": "PlayerRoundData",
    "playerId": "XXXXXXXXXXXXX",
    "groupId": "XXXXXXXXXXXXXX",
    "holeScores": [
      {
        "type": "RoundHoleData",
        "points": 2
      },
      {
        "type": "RoundHoleData",
        "points": 13
      },
      {
        "type": "RoundHoleData",
        "points": 3
      },
      {
        "type": "RoundHoleData",
        "points": 1
      },
      {
        "type": "RoundHoleData",
        "points": 21
      }
    ]
  }
}

Now, the tricky part of this is that I only want the average of points for holeScores[0] of all documents with this playerid and this groupid.

Actually, the best solution would be collecting all documents with playerid and groupid and create a new array with the average of holeScores[0], holeScores[1], holeScores[2]... But if I only can get one array key at the time, that would be OK to :-)

Here is what I am thinking but not quit sure how to put it together:

var allScores = dbCollection('scores').aggregate(
    {$match: {"data.groupId": groupId, "playerId": playerId}},
    {$group: {
        _id: playerId, 
        rounds: { $sum: 1 }
        result: { $sum: "$data.scoreTotals.points" }
    }}
);

Really hoping for help with this issue and thanks in advance :-)

2 Answers 2

1

You can use $unwind with includeArrayIndex to get index and then use $group to group by that index

dbCollection('scores').aggregate(
    {
        $match: { "data.playerId": "XXXXXXXXXXXXX", "data.groupId": "XXXXXXXXXXXXXX" }
    },
    {
        $unwind: {
            path: "$data.holeScores",
            includeArrayIndex: "index"
        }
    },
    {
        $group: {
            _id: "$index",
            playerId: { $first: "data.playerId" }, 
            avg: { $avg: "$data.holeScores.points" }
        }
    }
)
Sign up to request clarification or add additional context in comments.

3 Comments

It comes up with this error: Function aggregate does not accept parameters (object).? Any idea?
Perfect, it does the job. Have one question though. Is it possible to also get the playerid in the output of this before the array of averages?
@Mansa sure, modified my answer
1

You can try below aggregation

db.collection.aggregate(
  { "$match": { "data.groupId": groupId, "data.playerId": playerId }},
  { "$group": {
    "_id": null,
    "result": {
      "$sum": {
        "$arrayElemAt": [
          "$data.holeScores.points",
          0
        ]
      }
    }
  }}
)

1 Comment

It comes up with this error: Function aggregate does not accept parameters (object).? Any idea?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.