I have a collection of football matches shaped this way:
{
_id: ObjectId("SomeUniqueMatchID"),
players: [
{ team: "Arsenal", name: "Saka", distanceRan: 8590},
{ team: "Arsenal", name: "Aubameyang", distanceRan: 9230}
// ...remaining players for both teams
],
timestamp: 129380193,
// other match info
}
I want to query for the average distance ran by Aubameyang and Saka when playing together, regardless of the team they are in, as long as they are playing in the same.
I understand as far $unwind
on the players field, then $match
and finally using $group
to calculate the average, but I have no clue what to write on the $match condition when I don't know the team before running the query.
Query1
match_id
team
and push the distances in an arraynull
(all collection 1 group) and average the distance
(you don't care about what match, what team or which player, so only information about the avgDistance is kept)aggregate(
[{"$unwind": {"path": "$players"}},
{"$match":
{"$expr":
{"$or":
[{"$eq": ["$players.name", "Saka"]},
{"$eq": ["$players.name", "Aubameyang"]}]}}},
{"$group":
{"_id": {"_id": "$_id", "team": "$players.team"},
"distances": {"$push": "$players.distanceRan"}}},
{"$match": {"$expr": {"$eq": [{"$size": "$distances"}, 2]}}},
{"$unwind": {"path": "$distances"}},
{"$group": {"_id": null, "avgDistanceRan": {"$avg": "$distances"}}},
{"$unset": ["_id"]}])
Query2
aggregate(
[{"$set":
{"players":
{"$reduce":
{"input": "$players",
"initialValue": {"team": null, "distances": []},
"in":
{"$cond":
[{"$and":
[{"$or":
[{"$eq": ["$$this.name", "Saka"]},
{"$eq": ["$$this.name", "Aubameyang"]}]},
{"$or":
[{"$eq": ["$$value.team", null]},
{"$eq": ["$$value.team", "$$this.team"]}]}]},
{"team": "$$this.team",
"distances":
{"$concatArrays":
["$$value.distances", ["$$this.distanceRan"]]}},
"$$value"]}}}}},
{"$match": {"$expr": {"$eq": [{"$size": "$players.distances"}, 2]}}},
{"$unwind": {"path": "$players.distances"}},
{"$group":
{"_id": null, "avgdistanceRan": {"$avg": "$players.distances"}}},
{"$unset": ["_id"]}])