You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB如何给集合所有文档更新随机值并统计增量总和

你原有的遍历逐条调用save的实现,每次更新都会发起一次独立的数据库请求,大量IO开销导致运行速度慢;而直接用updateMany时随机值是在Node.js层提前计算的,只会生成一次,所以所有文档都会加同一个值。以下是两种可行的高性能解决方案:

方案一:批量写入(BulkWrite),全版本兼容,精度最高

该方案只需查询所有用户ID,在应用层生成每个用户的随机增量,一次性提交所有更新操作,相比逐条save性能提升数十倍,且总和计算完全精确。

const earnMoneyForUsers = async (batchSize = 5000) => {
  // 仅查询用户ID,减少数据传输开销
  const userIds = await User.find().distinct('_id');
  let totalEarnedMoney = 0;

  // 分批提交避免单次请求过大,适合百万级以上的集合
  for (let i = 0; i < userIds.length; i += batchSize) {
    const currentBatch = userIds.slice(i, i + batchSize);
    const bulkOps = currentBatch.map(userId => {
      const earnedMoneyByUser = Math.floor(Math.random() * 100);
      const increment = earnedMoneyByUser * 0.98; // 等价于扣除2%手续费后的增量
      totalEarnedMoney += increment;
      return {
        updateOne: {
          filter: { _id: userId },
          update: {
            $inc: {
              weeklyEarnedMoney: increment,
              totalEarnedMoney: increment
            }
          }
        }
      };
    });
    await User.bulkWrite(bulkOps);
  }

  return totalEarnedMoney;
};

方案二:MongoDB 4.4+ 数据库端聚合更新,性能最优

如果你的MongoDB版本 >= 4.4,可以直接在数据库层使用内置的$rand函数生成每个文档的独立随机值,无需将用户ID拉取到应用层,性能更高。需要注意如果需要总和和更新值严格一致,需要搭配事务使用,普通场景下误差可以忽略。

const earnMoneyForUsers = async () => {
  // 执行聚合更新,每个文档生成独立随机增量
  await User.updateMany({}, [
    {
      $addFields: {
        earnedMoneyByUser: { $floor: { $multiply: [{ $rand: {} }, 100] } }
      }
    },
    {
      $set: {
        increment: { $multiply: ["$earnedMoneyByUser", 0.98] }
      }
    },
    {
      $set: {
        weeklyEarnedMoney: { $add: ["$weeklyEarnedMoney", "$increment"] },
        totalEarnedMoney: { $add: ["$totalEarnedMoney", "$increment"] }
      }
    },
    {
      $unset: ["earnedMoneyByUser", "increment"]
    }
  ]);

  // 聚合统计所有增量的总和
  const sumRes = await User.aggregate([
    {
      $group: {
        _id: null,
        total: {
          $sum: {
            $multiply: [{ $floor: { $multiply: [{ $rand: {} }, 100] } }, 0.98]
          }
        }
      }
    }
  ]);
  return sumRes[0].total;
};

内容的提问来源于stack exchange,提问作者basedman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 23:48:02