0
votes

I am trying to use aggregation based on my mongoose model. Please look into this and help me out with the error and give any suggestions.Error: "message": { "message": "Cast to ObjectId failed for value \"tour-stats\" at path \"_id\" for model \"Tour\"",

Route

router.get('/tour-stats', tour.getTourStats);

Controller

exports.getTourStats = async (req, res) => {
try {
const stats = await Tour.aggregate([
  {
    $match: { ratingsAverage: { $gte: 4.5 } }
  },
  {
    $group: {
      _id: null,
      numTours: { $sum: 1 },
      numRatings: { $sum: '$ratingsQuantity' },
      avgRating: { $avg: '$ratingsAverage' },
      avgPrice: { $avg: '$price' },
      minPrice: { $min: '$price' },
      maxPrice: { $max: '$price' }
    }
  },
  {
    $sort: { avgPrice: 1 }
  }
  // {
  //   $match: { _id: { $ne: 'EASY' } }
  // }
]);

res.status(200).json({
  status: 'success',
  data: {
    stats
  }
});
} catch (err) {
res.status(404).json({
  status: 'fail',
  message: err
});
}
};

Tour Model

const tourSchema = new mongoose.Schema(
{
name: {
  type: String,
  required: [true, 'A tour must have a name'],
  unique: true,
  trim: true,
},
duration: {
  type: Number,
  required: [true, 'A tour must have a duration'],
},
maxGroupSize: {
  type: Number,
  required: [true, 'A tour must  have a group size'],
},
difficulty: {
  type: String,
  required: [true, 'A tour must have a difficulty'],
},
ratingsAverage: {
  type: Number,
  default: 4.5,
},
ratingsQuantity: {
  type: Number,
  default: 0,
},
price: {
  type: Number,
  required: [true, 'A tour must have a price '],
},
priceDiscount: Number,
summary: {
  type: String,
  trim: true,
  required: [true, 'A tour must have a decription'],
},
description: {
  type: String,
  trim: true,
},
imageCover: {
  type: String,
  required: [true, 'A tour must have a cover image'],
},
images: [String],
createdAt: {
  type: Date,
  default: Date.now(),
},
 startDates: [Date],
 }
 // { timestamps: true }
);

Sample document:

{ "id": 8, "name": "The Northern Lights", "duration": 3, "maxGroupSize": 12, "difficulty": "easy", "ratingsAverage": 4.9, "ratingsQuantity": 33, "price": 1497, "summary": "Enjoy the Northern Lights in one of the best places in the world", "description": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", "imageCover": "tour-9-cover.jpg", "images": ["tour-9-1.jpg", "tour-9-2.jpg", "tour-9-3.jpg"], "startDates": ["2021-12-16,10:00", "2022-01-16,10:00", "2022-12-12,10:00"] }

Thanks in Advance.

1

1 Answers

0
votes

I know it's a bit late to answer, but anyway. I've also took this course and was struggling to understand what's going on, and finally found it. In my case it happened because of the wrong order of the routes.

When you're trying to send request to "api/v1/tours/tour-stats" you actually sending request to "api/v1/tours/:id" and "tour-stats" goes as id to this route (obviously invalid), causing an error. So be sure that your "tour-stats" route defined before your id route.

enter image description here