I have a collection of User documents, containing several fields and an array of Bets. I am trying to set up an update that I will run on a schedule. In the User documents, the Balance field needs to be incremented by (Bets[index].multiplier * Bets[index].amount), and the Bets[index] needs to be marked as paid out and whether the bet was successful.
An example of a User document I’m trying to update. After running the update, User.bets[1].isPaidOut should be true, User.bets[1].didWin should be true, and User.balance should be incremented by 89 (that is, because ceiling(1.27 * 70) = 89).
{
"_id": {
"$oid": "63c9ca0217b00eaef7d6237f"
},
"guildId": "1061387401743831121",
"userId": "307884715677974530",
"userName": "Iron Man",
"balance": {
"$numberDouble": "100.0"
},
"lastClaimedAt": {
"$date": {
"$numberLong": "1674168834621"
}
},
"bets": [
{
"sport": "NFL",
"eventWeek": {
"$numberInt": "2"
},
"team": "New York Giants",
"opponentTeam": "Philadelphia Eagles",
"teamId": {
"$numberInt": "19"
},
"opponentTeamId": {
"$numberInt": "21"
},
"eventId": "401438004",
"amount": {
"$numberInt": "20"
},
"multiplier": {
"$numberDouble": "3.85"
},
"isPaidOut": true,
"didWin": false
},
{
"sport": "NFL",
"eventWeek": {
"$numberInt": "2"
},
"team": "Philadelphia Eagles",
"opponentTeam": "New York Giants",
"teamId": {
"$numberInt": "21"
},
"opponentTeamId": {
"$numberInt": "19"
},
"eventId": "401438004",
"amount": {
"$numberInt": "70"
},
"multiplier": {
"$numberDouble": "1.27"
},
"isPaidOut": false
},
{
"sport": "NFL",
"eventWeek": {
"$numberInt": "2"
},
"team": "San Francisco 49ers",
"opponentTeam": "Dallas Cowboys",
"teamId": {
"$numberInt": "25"
},
"opponentTeamId": {
"$numberInt": "6"
},
"eventId": "401438006",
"amount": {
"$numberInt": "200"
},
"multiplier": {
"$numberDouble": "1.49"
},
"isPaidOut": false
}
],
"createdAt": {
"$date": {
"$numberLong": "1674168834633"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1674338378566"
}
},
"__v": {
"$numberInt": "3"
}
}
This is what I have for my Update. When this is run, I receive this error: uncaught promise rejection: write exception: write errors: [Cannot increment with non-numeric argument: {balance: { $ceil: { $mul: [ "bets.$.amount", "bets.$.multiplier" ] } }}]
. I thought this could have been because of mismatched types, but all documents have the same as the one above.
const winnerId = 21;
const eventId = "401438004";
usersCollection.updateMany(
{
bets: {
"$elemMatch": {
eventId: eventId,
isPaidOut: false,
teamId: winnerId
}
}
},
{
$set: { "bets.$.isPaidOut" : true, "bets.$.didWin": true },
$inc: {
balance: {$ceil: {$mul: {"bets.$.amount": "bets.$.multiplier"} }}
}
}
);
2
Answers
$ceil is an aggregation operator, not an update operator, so you can only use it with an update if you use the update with aggregation pipeline
You will have to use pipelined update. But then, you won’t be able to use
$
field names. Here’s a solution using $map and $reduce.Demo