Mongoose: Model.aggregate returning an empty array

Viewed 59

I'm trying to calculate an average value based on the user's rating for the product.

My Schemas:

const journalSchema = new mongoose.Schema({
  title: String,
  category: String,
  subcategory: String,
  review: [{type: mongoose.Schema.Types.ObjectId, ref: 'Review'}],
  link: String,
  description: String,
  subscribers: Number,
  image: String
});

const reviewSchema  = new mongoose.Schema({
  author: {type: mongoose.Schema.Types.String, ref: 'User'},
  content: String,
  date: Date,
  rating: {type: Number, min: 1.0, max: 5.0}
});

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

Route:

app.get("/", function(req, res){
Journal.find({}, function(err, journals){
  if(err){
    console.log(err);
  }
  else{
      Review.aggregate([
        {$unwind: "$journals"},
        {$match: {_id: {$in: journals}}},
        {$unwind: "$journals.review"},
        {$group: {_id: journals.review, average: {$avg: "$rating"}}}
      ], function(err, results){
        if(err){
          console.log(err);
        }
        else{
          console.log(results);
        }
      })
    res.render("home", {journals: journals});
    }
  });
});

All I get is an empty array.

My goal is to render the page with shops that have a rating above 4. I can't figure out where the issue is. Is it possible to achieve this with other alternatives or using aggregate is the way to go?

1 Answers

You can use the aggregation method,

  • $lookup with reviews collection
  • $avg to get average of rating from reviews result
  • $match to filter journals by rating should greater than 4
app.get("/", function(req, res) {
  Journal.aggregate([
    {
      $lookup: {
        from: "reviews",
        localField: "review",
        foreignField: "_id",
        as: "review"
      }
    },
    {
      $addFields: { review: { $avg: "$review.rating" } }
    },
    {
      $match: {
        review: { $gt: 4 }
      }
    }
  ], 
  function(err, results) {
    if(err) { console.log(err); }
    else { 
      res.render("home", { journals: results });
    }
  })
});

Playground

Related