I have a collection that has following document structure:
{
"_id": {
"$oid": "663de073ccdaae20debc33b8"
},
"firstName": "Dejounte",
"lastName": "Murray",
"birth": {
"date": {
"$date": "1996-09-18T21:00:00.000Z"
},
"country": "USA"
},
"nba": {
"start": "2016",
"pro": 4
},
"height": {
"feets": 6,
"inches": 4,
"meters": 1.93
},
"weight": {
"pounds": 180,
"kilograms": 81.6
},
"college": "Washington",
"affiliation": "Washington/USA",
"leagues": {
"standard": {
"jersey": "5",
"active": true,
"position": "GUARD"
}
},
"teamBySeason": {
"_2023": {
"$oid": "6618ee274792f33fa3d6bc99"
}
},
"statsBySeason": {
"_2023": [
{
"game": {
"_id": 12490
},
"team": {
"_id": "1",
"name": "Atlanta Hawks",
"nickname": "Hawks",
"code": "ATL",
"logo": "https://upload.wikimedia.org/wikipedia/fr/e/ee/Hawks_2016.png"
},
"player": {
"_id": "382",
"firstName": "Dejounte",
"lastName": "Murray"
},
"position": "SHOOTING_GUARD",
"minutes": 17,
"uuid": {
"$binary": {
"base64": "CrLCbRzWTNGd/l5E5YmYxw==",
"subType": "04"
}
},
"points": 6,
"fgm": 2,
"fga": 7,
"fgp": 28.6,
"ftm": 0,
"fta": 0,
"ftp": 0,
"tpm": 2,
"tpa": 4,
"tpp": 50,
"offReb": 1,
"defReb": 1,
"totReb": 2,
"assists": 3,
"pFouls": 0,
"steals": 1,
"turnovers": 2,
"blocks": 0,
"plusMinus": 11
},
{
"game": {
"_id": 12503
},
"team": {
"_id": "1",
"name": "Atlanta Hawks",
"nickname": "Hawks",
"code": "ATL",
"logo": "https://upload.wikimedia.org/wikipedia/fr/e/ee/Hawks_2016.png"
},
"player": {
"_id": "382",
"firstName": "Dejounte",
"lastName": "Murray"
},
"position": "SHOOTING_GUARD",
"minutes": 17,
"uuid": {
"$binary": {
"base64": "C06xv2MvSQel1d25kdwzuA==",
"subType": "04"
}
},
"points": 7,
"fgm": 3,
"fga": 8,
"fgp": 37.5,
"ftm": 0,
"fta": 0,
"ftp": 0,
"tpm": 1,
"tpa": 4,
"tpp": 25,
"offReb": 0,
"defReb": 3,
"totReb": 3,
"assists": 3,
"pFouls": 0,
"steals": 2,
"turnovers": 0,
"blocks": 0,
"plusMinus": 2
},
{
"game": {
"_id": 12510
},
"team": {
"_id": "1",
"name": "Atlanta Hawks",
"nickname": "Hawks",
"code": "ATL",
"logo": "https://upload.wikimedia.org/wikipedia/fr/e/ee/Hawks_2016.png"
},
"player": {
"_id": "382",
"firstName": "Dejounte",
"lastName": "Murray"
},
"position": "SHOOTING_GUARD",
"minutes": 21,
"uuid": {
"$binary": {
"base64": "Q8sbxjOXSv+WeIfpSDBkSw==",
"subType": "04"
}
},
"points": 12,
"fgm": 4,
"fga": 7,
"fgp": 57.1,
"ftm": 2,
"fta": 2,
"ftp": 100,
"tpm": 2,
"tpa": 3,
"tpp": 66.7,
"offReb": 0,
"defReb": 7,
"totReb": 7,
"assists": 1,
"pFouls": 0,
"steals": 4,
"turnovers": 4,
"blocks": 0,
"plusMinus": 23
}
]
}
}
I need to calculate each individual player efficiency for a given season using this formula:
(points + totReb + assists + steals + blocks) - ((fga - fgm) + (fta - ftm) + turnovers)
Then find top 10 players with the highest evaluated value and return them.
This is my Java domain models:
@Document(PlayerData.COLLECTION_NAME)
public class PlayerData extends APINbaIdentifier {
public static final String COLLECTION_NAME = "players";
private String firstName;
private String lastName;
private PlayerBirth birth;
private CareerData nba;
private HeightData height;
private WeightData weight;
private String college;
private String affiliation;
private Map<String, League> leagues;
@DocumentReference(lazy = true)
private Map<SupportedSeasons, TeamData> teamBySeason;
private Map<SupportedSeasons, List<PlayerStats>> statsBySeason;
// Constructor, getters, setters...
}
@JsonIgnoreProperties("id")
public class PlayerStats extends Stats {
private GameId game;
private TeamId team;
private PlayerId player;
private PlayerGamePosition position;
private int minutes;
}
public class Stats implements IdAware<UUID> {
private UUID uuid;
private int points;
private int fgm;
private int fga;
private double fgp;
private int ftm;
private int fta;
private double ftp;
private int tpm;
private int tpa;
private double tpp;
private int offReb;
private int defReb;
private int totReb;
private int assists;
private int pFouls;
private int steals;
private int turnovers;
private int blocks;
private int plusMinus;
}
What I’ve tried so far:
ProjectionOperation efficiency =
Aggregation.project()
.andExpression("(statsBySeason._2023.points + statsBySeason._2023.totReb + statsBySeason._2023.assists + statsBySeason._2023.steals + statsBySeason._2023.blocks)" +
" - ((statsBySeason._2023.fga - statsBySeason._2023.fgm) + (statsBySeason._2023.fta - statsBySeason._2023.ftm) + statsBySeason._2023.turnovers)")
.as("efficiency");
UnwindOperation unwind = Aggregation.unwind("statsBySeason._2023");
GroupOperation avgEfficiency = Aggregation.group("statsBySeason._2023").avg("efficiency").as("avgEfficiency");
TypedAggregation<PlayerData> aggregation = Aggregation.newAggregation(PlayerData.class, efficiency, unwind, avgEfficiency);
List<PlayerData> mappedResults = mongotemplate.aggregate(aggregation, PlayerData.class).getMappedResults();
Which gives an exception:
Caused by: com.mongodb.MongoCommandException: Command failed with error 7157723 (Location7157723): 'PlanExecutor error during aggregation :: caused by :: only numbers and dates are allowed in an $add expression' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "PlanExecutor error during aggregation :: caused by :: only numbers and dates are allowed in an $add expression", "code": 7157723, "codeName": "Location7157723"}