实现思路
- 筛选评论:使用
$match
阶段筛选出评分大于等于4分且评论时间在最近30天内的评论。假设reviewTime
为日期类型,可通过$gte
操作符结合$subtract
计算当前日期减去30天来筛选。
{
$match: {
rating: { $gte: 4 },
reviewTime: {
$gte: {
$subtract: [new Date(), 30 * 24 * 60 * 60 * 1000]
}
}
}
}
- 按商品ID分组并统计:使用
$group
阶段,按照商品ID进行分组,计算每个商品的平均评分($avg
)、评论总数($sum
)以及好评数($sum
结合条件判断),进而计算好评率。
{
$group: {
_id: "$productId",
averageRating: { $avg: "$rating" },
totalReviews: { $sum: 1 },
positiveReviews: {
$sum: {
$cond: [
{ $gte: ["$rating", 4] },
1,
0
]
}
}
}
}
- 计算好评率并再次筛选:在另一个
$project
阶段计算好评率,并使用$match
筛选出平均评分大于4.5且好评率大于80%的商品。
{
$project: {
productId: "$_id",
averageRating: 1,
totalReviews: 1,
positiveReviews: 1,
positiveRate: {
$cond: [
{ $gt: ["$totalReviews", 0] },
{ $divide: ["$positiveReviews", "$totalReviews"] },
0
]
}
}
},
{
$match: {
averageRating: { $gt: 4.5 },
positiveRate: { $gt: 0.8 }
}
}
- 按平均评分降序排列:最后使用
$sort
阶段按平均评分降序排列。
{
$sort: {
averageRating: -1
}
}
性能瓶颈及优化措施
- 大数据量下
$match
筛选性能问题:
- 瓶颈:在超大数据量下,
$match
筛选操作可能会因为需要遍历大量文档而性能低下。
- 优化:确保
rating
和reviewTime
字段上有合适的索引。可以使用复合索引,例如createIndex({rating: 1, reviewTime: 1})
,以加速筛选过程。
$group
阶段性能瓶颈:
- 瓶颈:
$group
操作需要对数据进行分组,在大数据量时内存消耗大,且处理时间长。
- 优化:如果数据量过大,可以考虑分阶段聚合。先在部分数据上进行本地聚合,然后再将这些聚合结果进行最终的全局聚合。另外,可以增加内存限制来提高
$group
操作的性能,但要注意服务器的实际内存情况。
- 排序性能问题:
- 瓶颈:
$sort
操作在大数据量下,特别是当需要排序的数据量接近或超过内存大小时,性能会急剧下降。
- 优化:在排序字段
averageRating
上创建索引createIndex({averageRating: -1})
。并且如果可能,尽量减少参与排序的数据量,例如在排序前先进行筛选操作。