如何为MongoDB所有嵌入式数组文档分别添加独立随机数
问题根因
你当前的代码存在两个核心问题:
Math.random()是在Node服务端拼接更新语句时执行的,整个请求生命周期里只会运行1次,生成的固定值会被传给MongoDB,导致所有被更新的评论项拿到同一个随机评分- 你调用的是
updateOne方法,只会更新第一条匹配{ reviews: { $ne: [] } }条件的父文档,无法批量更新所有符合要求的记录
修复方案
MongoDB 4.2及以上版本支持聚合管道形式的更新操作,你可以把随机数生成逻辑放到MongoDB侧执行,利用内置操作符在遍历每个数组元素时单独生成随机值,同时替换updateOne为updateMany实现批量更新。
修复后的完整代码:
app.patch("/updatemany", async (req, res, next) => { const updateResult = await listingsAndReview.updateMany( // 筛选存在非空评论数组的文档 { reviews: { $ne: [] } }, // 传数组标识使用聚合更新管道,逻辑在MongoDB侧执行 [ { $set: { reviews: { $map: { input: "$reviews", in: { // 保留评论原有字段,仅覆盖rating值 $mergeObjects: [ "$$this", { rating: { // 和原有JS计算逻辑对齐:生成1-5区间、保留1位小数的评分 $add: [ 1, { $round: [ { $multiply: [{ $rand: {} }, 4] }, 1 ] } ] } } ] } } } } } ], { upsert: true } ); res.send(updateResult); });
关键逻辑说明
- 聚合管道内的
$rand是MongoDB内置的随机数生成操作符,$map每处理一条评论子文档时都会重新生成0-1之间的随机值,保证每个评论的评分都是独立生成的 $mergeObjects会合并原有评论对象和新生成的rating字段,不会丢失评论原本存的内容、作者、时间等其他字段updateMany会遍历所有符合筛选条件的父文档,不会只更新第一条匹配记录
内容的提问来源于stack exchange,提问作者Sibi
相关产品推荐
相关产品推荐

