【发布时间】:2020-05-27 03:48:54
【问题描述】:
我正在尝试使用 express/mongoose 构建一种 yelp 克隆,并且需要能够返回一个包含每个评分类别的平均分数的对象(例如:全球、位置、食物和环境) ,每个来自不同的审阅子文档。一个示例餐厅看起来像这样(我去掉了不相关的字段):
{
name: 'Test Restaurant',
reviews: [
{
_id: 5e42c12e903eac188077dca5,
rating: {
global: 10,
location: 5,
food: 8,
ambient: 6
}
},
{
_id: 5e42c12e903eac188077dca6,
rating: {
global: 5,
location: 6,
food: 4,
ambient: 2
}
},
{
_id: 5e42c12e903eac188077dca7,
rating: {
global: 9,
location: 3,
food: 5,
ambient: 1
}
},
]
}
到目前为止,我已经能够使用以下虚拟机做到这一点,但我认为如果评论数量增长到足够大,这将很快变得低效:
restaurantSchema.virtual("averageRatings").get(function() {
const restaurant = this;
const ratings = restaurant.reviews.map(review => review.rating);
const ratingsArrays = {};
const averageRatings = {};
const categories = [
"global",
"food",
"ambient",
"location"
];
//Loop for every category, create new array with the ratings from each review per category, and filter out null ratings
categories.forEach(category => {
ratingsArrays[category] = ratings
.map(rating => rating[category])
.filter(value => value != null);
//Calculate average for each category, and return undefined where there are not ratings
averageRatings[category] =
ratingsArrays[category].reduce((acc, current) => acc + current, 0) /
ratingsArrays[category].length || undefined;
});
return averageRatings;
});
现在,我已经看到更有效/更正确的方法是使用 MongoDB 聚合框架,但即使我查看了手册并找到了针对特定情况的一些非常好的答案,但我还没有在这种特殊情况下能够解决它。
可以帮助我找到一个我可以使用的近似管道吗?您是否知道任何资源可以比官方手册更友好地学习 MongoDB 查询/聚合语法(SQL 类似:https://sqlbolt.com/)?
【问题讨论】:
标签: database mongodb mongoose aggregation-framework