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)