#node.js #mongodb #aggregation-framework
Вопрос:
У меня есть модель продукта, которая выглядит так:
{
"name":"Natural Product",
"ratings":[
{
"user":"5fdce4bd75dbe4864fcd5001",
"rating":5
},
{
"user":"5fdce4bd75dbe4864fcd5002",
"rating":4
}
]
}
Я попытался получить среднюю оценку модели продукта, используя запрос ниже
db.products.aggregate([
{$match: {
_id: {$exists: true}
}},
{$group: {_id: "$_id", rating: { $avg: "$ratings.rating"}}}
])
Но тогда ответ, который я получаю, выглядит так:
{ "_id" : ObjectId("60baf573246539ec265efd41"), "rating" : null }
Пытаясь понять, в чем проблема, я вставил новые фиктивные данные только с небольшой разницей в структуре, которая выглядит следующим образом:
{
"name":"Natural Product",
"ratings":{
"user": "5fdce4bd75dbe4864fcd5001",
"rating": 5
}
}
Это дало мне такой разумный ответ:
{ "_id" : ObjectId("60bafb72246539ec265efd42"), "rating" : 5 }
Как я должен запросить базу данных, чтобы получить среднее значение оценок в формате массива, пожалуйста?
Комментарии:
1. добавьте новый этап после этапа $match
{ $unwind: "$ratings" }
, это приведет к деконструированию массива рейтингов.
Ответ №1:
$avg можно использовать на этапе $project, если у вас более новая версия, чем mongodb server v3.2
db.products.aggregate(
[
{
$project: {
_id: 1,
rating: { $avg: "$ratings.rating" }
}
}
])
Ответ №2:
Выполнение этого на массиве объектов сбивает с толку. Монго не знает, к какому элементу массива обращаться. Так что нам это нужно для unwind
того, чтобы разобрать его.
Это сработает
db.collection.aggregate([
{
$match: {
_id: {
$exists: true
}
}
},
{
$unwind: "$ratings"
},
{
$group: {
_id: "$_id",
rating: {
$avg: "$ratings.rating"
}
}
}
])