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

MongoDB技术问题:如何更新已查询到的文档(电影评分系统场景)

电影评分系统中Content文档的正确更新方式

原代码存在的问题

  1. Content查询条件错误:原代码中Content.findOne使用_id: document._id,这里把Rating文档的ID当成了Content的ID,应该替换为req.body.contentId(或document.contentId),因为Rating中存储的contentId才是对应Content的唯一标识。
  2. 平均分计算逻辑错误:原公式(content.average + document.rating) / content.count + 1不符合加权平均的计算规则,正确逻辑应为**(当前总分 + 新评分)/ 新的评分次数**。
  3. 服务器错误状态码误用:服务器内部错误应返回500而非404,404用于标识资源不存在。

修正方案一:直接修改文档对象并保存

这种方式直观易懂,适合低并发场景:

router.post('/', authenticate, async (req: IRequest<IRating>, res) => {
  try {
    const ratingDoc = await Rating.create({
      contentId: req.body.contentId,
      contentType: req.body.contentType,
      rating: req.body.rating,
      review: req.body.review,
      userId: req.user?._id,
    });

    // 修正查询条件,用内容ID查找对应的Content文档
    const content = await Content.findOne({
      type: req.body.contentType,
      _id: req.body.contentId,
    });

    if (content) {
      // 计算新的评分次数和平均分
      const newCount = content.count + 1;
      const newAverage = (content.average * content.count + ratingDoc.rating) / newCount;
      
      // 修改文档属性后直接保存
      content.count = newCount;
      content.average = newAverage;
      await content.save();
    }

    res.json({ success: true, rating: ratingDoc, content });
  } catch (err) {
    // 修正服务器错误状态码
    res.status(500).json({ success: false, message: '服务器错误' });
  }
});

修正方案二:原子更新(推荐高并发场景)

使用MongoDB的原子操作,在数据库层面保证操作的原子性,避免并发读写导致的数据不一致问题:

router.post('/', authenticate, async (req: IRequest<IRating>, res) => {
  try {
    const ratingDoc = await Rating.create({
      contentId: req.body.contentId,
      contentType: req.body.contentType,
      rating: req.body.rating,
      review: req.body.review,
      userId: req.user?._id,
    });

    // 原子更新Content文档,直接在数据库层面计算新的count和average
    const updatedContent = await Content.findOneAndUpdate(
      {
        type: req.body.contentType,
        _id: req.body.contentId,
      },
      [
        {
          $set: {
            count: { $add: ['$count', 1] },
            average: {
              $divide: [
                { $add: [{ $multiply: ['$average', '$count'] }, ratingDoc.rating] },
                { $add: ['$count', 1] }
              ]
            }
          }
        }
      ],
      { new: true } // 配置返回更新后的文档
    );

    res.json({ success: true, rating: ratingDoc, content: updatedContent });
  } catch (err) {
    res.status(500).json({ success: false, message: '服务器错误' });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:31:16