1

I have a product model that looks thus:

{
   "name":"Natural Product",
   "ratings":[
      {
         "user":"5fdce4bd75dbe4864fcd5001",
         "rating":5
      },
      {
         "user":"5fdce4bd75dbe4864fcd5002",
         "rating":4
      }
   ]
}

I tried to get the average rating of the product model using the query below

db.products.aggregate([
  {$match: {
    _id: {$exists: true}
  }},
  {$group: {_id: "$_id", rating: { $avg: "$ratings.rating"}}}
])

But then the response I get looks thus:

{ "_id" : ObjectId("60baf573246539ec265efd41"), "rating" : null }

While trying to figure what the problem is, I inserted a new dummy data just with a slight difference in the structure that looks thus:

{
   "name":"Natural Product",
   "ratings":{
     "user": "5fdce4bd75dbe4864fcd5001",
     "rating": 5
   }
}

It gave me this reasonable response:

{ "_id" : ObjectId("60bafb72246539ec265efd42"), "rating" : 5 }

How am I supposed to query the database to get the average of the ratings which is in array format, please?

1
  • 1
    add new stage after $match stage, { $unwind: "$ratings" }, it will deconsturct the ratings array. Commented Jun 5, 2021 at 15:29

2 Answers 2

1

$avg can be used in the $project stage if you have newer than mongodb server v3.2

db.products.aggregate(
[
    {
        $project: {
            _id: 1,
            rating: { $avg: "$ratings.rating" }
        }
    }
])

https://mongoplayground.net/p/uehHGxI3ybU

Sign up to request clarification or add additional context in comments.

Comments

1

Doing this on array of objects is confusing. Mongo doesn't know which element to access in the array. So we need to unwind it in order to deconstruct it.
This will work

db.collection.aggregate([
  {
    $match: {
      _id: {
        $exists: true
      }
    }
  },
  {
    $unwind: "$ratings"
  },
  {
    $group: {
      _id: "$_id",
      rating: {
        $avg: "$ratings.rating"
      }
    }
  }
])

Working example for mongo playground

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.