由于值“NaN”而转换为数字失败

问题描述 投票:0回答:1

所以,问题是我正在尝试添加相关产品的评论。但每当我尝试通过 Postman 访问 API 时,都会出现错误

ValidationError: Product validation failed: rating: Cast to Number failed for value "NaN" (type number) at path "rating"
[0]     at Document.invalidate (E:\Web\Shop.co\node_modules\mongoose\lib\document.js:3197:32)
[0]     at model.$set (E:\Web\Shop.co\node_modules\mongoose\lib\document.js:1456:12)
[0]     at model.set [as rating] (E:\Web\Shop.co\node_modules\mongoose\lib\helpers\document\compile.js:205:19)
[0]     at E:\Web\Shop.co\backend\controller\productController.js:108:20
[0]     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

这是产品架构

const mongoose = require("mongoose");

const reviewSchema = mongoose.Schema(
  {
    name: { type: String, required: true },
    rating: { type: Number, required: true, default: 0 },
    comment: { type: String, required: true },
    user: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: "User",
    },
  },
  {
    timestamps: true,
  }
);

const productSchema = mongoose.Schema(
  {
    user: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: "User",
    },

    name: {
      type: String,
      required: true,
    },
    image: {
      type: String,
      required: true,
    },
    brand: {
      type: String,
      required: true,
    },
    category: {
      type: String,
      required: true,
    },
    description: {
      type: String,
      required: true,
    },
    price: {
      type: Number,
      required: true,
      default: 0,
    },
    review: [reviewSchema],
    rating: {
      type: Number,
      required: true,
      default: 0,
    },
    numReviews: {
      type: Number,
      required: true,
      default: 0,
    },
    countInStock: {
      type: Number,
      required: true,
      default: 0,
    },
  },
  {
    timestamps: true,
  }
);

const Product = mongoose.model("Product", productSchema);

module.exports = Product;

这是产品控制器中的 createReview 函数

const createReview = asyncHandler(async (req, res) => {
  const { rating, comment } = req.body;
  const product = await Product.findById(req.params.id);
  if (product) {
    const alreadyReviewed = product.review.find(
      (r) => r.user.toString() === req.user._id.toString()
    );

    if (alreadyReviewed) {
      res.status(400).json({ message: " Product already reviewed" });
      throw new Error("Product already reviewed");
    }

    const reviews = {
      name: req.user.name,
      rating: Number(rating),
      comment,
      user: req.user._id,
    };
    product.review.push(reviews);

    product.numReviews = product.review.length;
    product.rating =
      product.review.reduce((item, acc) => item.rating + acc, 0) /
      product.review.length;

    await product.save();
    res.status(100).json({ message: " Review Added" });
  } else {
    res.status(400).json({ message: " Product not found" });
    throw new Error("Product not found");
  }
});

路线是

router.route("/:id/reviews").post(protect, createReview);

虽然评分被定义为 Number 类型并在创建评论时给定 Number,但它仍然给出 NaN 错误。

如果我错了或者我的代码错误,请给我建议,先谢谢你!

node.js express routes postman
1个回答
0
投票

发生错误是因为reduce函数没有正确总结评论的评分。

要解决此问题,您需要通过正确总结所有评论的评分来调整产品评分的计算。这是 createReview 函数的更正版本

const createReview = asyncHandler(async (req, res) => {
  const { rating, comment } = req.body;
  const product = await Product.findById(req.params.id);
  
  if (product) {
    const alreadyReviewed = product.review.find(
      (r) => r.user.toString() === req.user._id.toString()
    );

    if (alreadyReviewed) {
      res.status(400).json({ message: "Product already reviewed" });
      throw new Error("Product already reviewed");
    }

    const review = {
      name: req.user.name,
      rating: Number(rating),
      comment,
      user: req.user._id,
    };
    
    product.review.push(review);
    product.numReviews = product.review.length;

    // Calculate new average rating
    const totalRating = product.review.reduce((acc, item) => acc + item.rating, 0);
    product.rating = totalRating / product.review.length;

    await product.save();
    res.status(200).json({ message: "Review Added" });
  } else {
    res.status(404).json({ message: "Product not found" });
    throw new Error("Product not found");
  }
});

© www.soinside.com 2019 - 2024. All rights reserved.