Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Cast to Number failed for value "NaN"

so, the problem is that I’m trying to add reviews for the related product. But whenever I tried to hit API through Postman it gave me an error

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)

This is the Product Schema

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;

and this is the createReview function in the Product Controller

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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");
  }
});

routes are

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

although the rating is defined as Number type and given Number during review creation, it still gives NaN error.

If I’m wrong or my code is wrong, please give me advice.

>Solution :

The error occurs because the reduce function is not correctly summing up the ratings of the reviews.

To fix this, you need to adjust the calculation of the product’s rating by correctly summing up the ratings of all reviews. Here’s the corrected version of your createReview function

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");
  }
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading