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

Mongoose Query中间件报Query has already execute错误求助

问题解决方法

报错原因

  • Mongoose 6.0+ 版本默认禁止同一个查询实例重复执行,你在pre(/^findOneAnd/)钩子中调用this.findOne()已经执行了一次查询,后续原findOneAndXXX(更新/删除类)操作要再次执行同一个查询实例就触发了Query was already executed报错。
  • 你的post(/^findOneAnd/)钩子中存在笔误,将评论关联的商品字段product错写为tour,会导致后续计算平均评分时传入的商品ID无效。
  • 可选边界问题:当商品下所有评论都被删除时,聚合返回的stats数组为空,直接取stats[0]会抛出空指针错误。

修复方案

1. 给pre钩子的findOne调用添加clone()

clone()方法会生成新的查询实例,避免和原查询的执行逻辑冲突:

reviewSchema.pre(/^findOneAnd/, async function (next) {
  this.r = await this.findOne().clone();
  next();
});

2. 修正post钩子的字段笔误

把关联字段从错误的tour改为正确的product:

reviewSchema.post(/^findOneAnd/, async function () {
  const model = this.r.constructor;
  await model.calcAverageRatings(this.r.product);
});

3. 优化calcAverageRatings的边界处理

增加空数组判断,避免删除所有评论时报错:

reviewSchema.statics.calcAverageRatings = async function (productId) {
  const stats = await this.aggregate([
    {
      $match: { product: productId },
    },
    {
      $group: {
        _id: "$product",
        numRating: { $sum: 1 },
        avgRating: { $avg: "$rating" },
      },
    },
  ]);
  if (stats.length > 0) {
    await Product.findByIdAndUpdate(productId, {
      ratingsAverage: stats[0].avgRating,
      ratingsQuantity: stats[0].numRating,
    });
  } else {
    // 无评论时重置为默认值
    await Product.findByIdAndUpdate(productId, {
      ratingsAverage: 4.5, // 可替换为你的业务默认评分
      ratingsQuantity: 0,
    });
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:09:01