Home > Blockchain >  Query to calculate and return average rating from another collection?
Query to calculate and return average rating from another collection?

Time:11-08

I have two collections, computers which is shown below

{"_id":{"$oid":"6185bee4aca3214e77e748a9"},"name":"Gaming PC","manufacturer":"Dell","category":["Gaming"],"colour":"black","price":1200.0,"quantity":47.0,"weight":10.0,"parts":[{"type":"motherboard","manufacturer":"AMD","cost":150.0,"description":"Motherboard suitable for gaming PCs"},{"type":"ram","manufacturer":"Corsair","cost":50.0,"description":"16gb 2400mhz RAM"},{"type":"cpu","manufacturer":"Intel","cost":250.0,"description":"AMD 5600X Processor"},{"type":"gpu","manufacturer":"NVIDIA","cost":600.0,"description":"NVIDIA GTX3080"},{"type":"storage","manufacturer":"Seagate","cost":80.0,"description":"1TB SSD"}],"reviews":["review01","review02","review10"]},

{"_id":{"$oid":"6185c06eaca3214e77e748aa"},"name":"Office PC","manufacturer":"HP","category":["Work","Office"],"colour":"black","price":400.0,"quantity":102.0,"weight":12.0,"parts":[{"type":"motherboard","manufacturer":"XYZ","cost":70.0,"description":"Reliable motherboard"},{"type":"ram","manufacturer":"HP","cost":10.0,"description":"4gb 2400mhz RAM"},{"type":"cpu","manufacturer":"Intel","cost":100.0,"description":"Built In Processor"},{"type":"gpu","manufacturer":"HP","cost":75.0,"description":"On board graphics"},{"type":"storage","manufacturer":"Seagate","cost":20.0,"description":"1TB HDD"}],"reviews":["review03"]},

{"_id":{"$oid":"6185c244aca3214e77e748ab"},"name":"Chromebook","manufacturer":"Acer","category":["Portable","Lightweight","Work","Student"],"colour":"red","price":350.0,"quantity":61.0,"weight":4.0,"parts":[{"type":"motherboard","manufacturer":"XYZ","cost":40.0,"description":"Reliable motherboard for Laptops"},{"type":"ram","manufacturer":"Acer","cost":10.0,"description":"Built in 4gb RAM"},{"type":"cpu","manufacturer":"AMD","cost":100.0,"description":"Built In Processor"},{"type":"gpu","manufacturer":"Acer","cost":45.0,"description":"On board graphics"},{"type":"storage","manufacturer":"Acer","cost":25.0,"description":"64GB HDD"}],"reviews":["review04","review05"]}

And the reviews collection;

{"_id":"review01","reviewer":"Jack Weir","rating":5.0,"text":"Very good product!","created":"2021, 08, 03"},
{"_id":"review02","reviewer":"Adam Smith","rating":3.0,"text":"Good value for money","created":"2021, 09, 04"},
{"_id":"review03","reviewer":"Luke Bridges","rating":1.0,"text":"Not good!","created":"2021, 10, 21"},
{"_id":"review04","reviewer":"Richard Lamb","rating":4.0,"text":"Runs very smoothly","created":"2021, 11, 03"},
{"_id":"review05","reviewer":"Pamela Halpert","rating":4.0,"text":"Easy to setup","created":"2021, 11, 04"},
{"_id":"review06","reviewer":"Michael Scott","rating":5.0,"text":"Would highly recommend","created":"2021, 11, 05"},
{"_id":"review07","reviewer":"Angela Lewis","rating":2.0,"text":"A bit too pricey","created":"2021, 11, 06"},
{"_id":"review08","reviewer":"Dexter Morgan","rating":3.0,"text":"Does the job","created":"2021, 11, 06"},
{"_id":"review09","reviewer":"Lisa Simpson","rating":2.0,"text":"Okay but not great","created":"2021, 11, 06"},
{"_id":"review10","reviewer":"Marge Simpson","rating":5.0,"text":"Wonderful Computer exactly what I was after!","created":"2021, 11, 07"}

How do I write a query that can return the name of each product and the average rating it has received from any ratings in the review property?

For example I would like the result of the query to show 'name: "Gaming PC", Average rating: 4.3'

CodePudding user response:

You only need a $lookup to join collections (get reviewers data into computers collection) and do $avg to get the average.

db.computers.aggregate({
  "$lookup": {
    "from": "reviews",
    "localField": "reviews",
    "foreignField": "_id",
    "as": "reviewers"
  }
},
{
  "$project": {
    "name": 1,
    "avg": {
      "$avg": "$reviewers.rating"
    }
  }
})

Example here

This query only outputs name and avg fields, but you can add into $project stage as many fields as you want. Also you can use $set or $addFields instead of project to not lose all values (example)

  • Related