Is there a way to update all documents in a collection with a random value in MongoDB?

Viewed 126

I want to increase a field in all documents with a random value and return the sum of all the increments. I made it work by iterating through all collection but obviously it is very slow.

const earnMoneyForUsers = async () => {
  let usersCursor = await User.find()
    .select({ name: 1, weeklyEarnedMoney: 1, totalEarnedMoney: 1 })
    .cursor()
  let totalEarnedMoney = 0

  await usersCursor.eachAsync((user) => {
    let earnedMoneyByUser = Math.floor(Math.random() * 100)
    let collectedAmount = earnedMoneyByUser * 0.02

    user.weeklyEarnedMoney += earnedMoneyByUser - collectedAmount
    user.totalEarnedMoney += earnedMoneyByUser - collectedAmount
    totalEarnedMoney += earnedMoneyByUser - collectedAmount
    user.save()
  })

  return totalEarnedMoney
}

I tried updateMany also but it updates all values with same random value and I don't know how I can sum the increment?

const earnMoneyForUsers = async () => {
  await User.updateMany(
    {},
    { $inc: { weeklyEarnedMoney: Math.floor(Math.random() * 100) } }
  )

  return ?
}
1 Answers

you can use $rand aggregation operator, and do a pipeline update like the bellow, doing all the calculations in the database, without sending data to the application.

The bellow is a way to re-write your code in MQL

let earnedMoneyByUser = Math.floor(Math.random() * 100)  
let collectedAmount = earnedMoneyByUser * 0.02  
user.weeklyEarnedMoney += earnedMoneyByUser - collectedAmount  
user.totalEarnedMoney += earnedMoneyByUser - collectedAmount  

PlayMongo

update(
{},
[{"$set": 
   {"earnedMoneyByUser": {"$toInt": {"$multiply": [{"$rand": {}}, 100]}}}},
 {"$set": 
   {"collectedAmount": {"$multiply": ["$earnedMoneyByUser", 0.02]}}},
 {"$set": 
   {"weeklyEarnedMoney": 
     {"$add": 
       ["$weeklyEarnedMoney",
         {"$subtract": ["$earnedMoneyByUser", "$collectedAmount"]}]}}},
 {"$set": 
   {"totalEarnedMoney": 
     {"$add": 
       ["$weeklyEarnedMoney",
         {"$subtract": ["$earnedMoneyByUser", "$collectedAmount"]}]}}}],
{"multi": true})
Related