1

When I execute this model,I get error. Please solve this question. This problem brought me headache. Opposed to using 'Content here, content here', making it look like readable English, many desktop publishing packages and web page editors now use 'Lorem Ipsum' as their default model text, and a search for 'Lorem Ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years.

const mongoose = require("mongoose");
const Product = require("./shopingModel");

const reviewSchema = new mongoose.Schema({
  createdAt: {
    type: Date,
    default: Date.now(),
  },
  review: {
    type: String,
    required: [true, "A review should not be empty"],
  },
  rating: {
    type: Number,
    min: [1, "rating shount below 1"],
    max: [5, "rating must be below 5.0"],
  },
  user: {
    type: mongoose.Schema.ObjectId,
    ref: "User",
    required: [true, "A review must belong a user"],
  },
  product: {
    type: mongoose.Schema.ObjectId,
    ref: "Product",
    required: [true, "A review must belong a product"],
  },
});

reviewSchema.pre(/^findOne/, function (next) {
  this.populate("user", "name").populate("product", "title price");

  next();
});

reviewSchema.statics.calcAverageRatings = async function (productId) {
  const stats = await this.aggregate([
    {
      $match: { product: productId },
    },
    {
      $group: {
        _id: "$product",
        numRating: { $sum: 1 },
        avgRating: { $avg: "$rating" },
      },
    },
  ]);
  await Product.findByIdAndUpdate(productId, {
    ratingsAverage: stats[0].avgRating,
    ratingsQuantity: stats[0].numRating,
  });
};

reviewSchema.post("save", async function () {
  await this.constructor.calcAverageRatings(this.product);
});

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

reviewSchema.post(/^findOneAnd/, async function () {
  // await this.findOne(); does NOT work here, query has already executed
  const model = this.r.constructor;
  await model.calcAverageRatings(this.r.tour);
});

const Review = mongoose.model("Review", reviewSchema);

module.exports = Review;

when i run calcAverageRatings on middleware then i got this

"status": "error",
"error": {
    "originalStack": "Error\n    at model.Query._wrappedThunk [as _findOne] (C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)\n    at C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:279:20\n    at _next (C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:103:16)\n    at C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:508:38\n    at processTicksAndRejections (internal/process/task_queues.js:77:11)",
    "status": "error",
    "statusCode": 500
},
"message": "Query was already executed: Review.findOne({ _id: new ObjectId(\"615d82ac971aae7627c5a1b9...",
"stack": "MongooseError: Query was already executed: Review.findOne({ _id: new ObjectId(\"615d82ac971aae7627c5a1b9...\n    at model.Query._wrappedThunk [as _findOneAndDelete] (C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:21:19)\n    at C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:279:20\n    at _next (C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:103:16)\n    at C:\\Users\\grixx\\Desktop\\Practice\\node_modules\\kareem\\index.js:508:38\n    at processTicksAndRejections (internal/process/task_queues.js:77:11)"
Mousumi Roy
  • 609
  • 1
  • 6
Grixx Nixx
  • 11
  • 3

2 Answers2

2

Use this.r = await this.clone().findOne(); instead of this.r = await this.findOne();

Vardaan
  • 101
  • 1
  • 5
0

I've been dealing with the same problem as you. I guess you were taking Jonas' course like me so I searched some solutions for this problem and found something like this in the course's QA section

reviewSchema.post(/^findOneAnd/, async function (doc, next) {
  await doc.constructor.calcAvgRatings(doc.tour);
  next();
});

The above solution this.clone().findOne() is working also but still just wanted to share another solution.

utkuonursahin
  • 249
  • 4
  • 10