MST
星途 面试题库

面试题:MongoDB聚合管道性能优化与复杂场景应用

在一个超大型的电商商品评论集合reviews中,每个文档包含商品ID(productId)、评论者ID(reviewerId)、评论内容(content)、评论时间(reviewTime)、评分(rating)等字段。现在要求使用聚合管道实现以下复杂功能并进行性能优化:首先,筛选出评分大于等于4分且评论时间在最近30天内的评论。然后,按照商品ID分组,统计每个商品的平均评分、评论总数以及好评率(好评指评分大于等于4分)。最后,只返回平均评分大于4.5且好评率大于80%的商品信息,并按照平均评分降序排列。请详细阐述实现思路,并指出在实际大数据量场景下可能遇到的性能瓶颈以及优化措施。
25.8万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 筛选评论:使用$match阶段筛选出评分大于等于4分且评论时间在最近30天内的评论。假设reviewTime为日期类型,可通过$gte操作符结合$subtract计算当前日期减去30天来筛选。
{
    $match: {
        rating: { $gte: 4 },
        reviewTime: {
            $gte: {
                $subtract: [new Date(), 30 * 24 * 60 * 60 * 1000]
            }
        }
    }
}
  1. 按商品ID分组并统计:使用$group阶段,按照商品ID进行分组,计算每个商品的平均评分($avg)、评论总数($sum)以及好评数($sum结合条件判断),进而计算好评率。
{
    $group: {
        _id: "$productId",
        averageRating: { $avg: "$rating" },
        totalReviews: { $sum: 1 },
        positiveReviews: {
            $sum: {
                $cond: [
                    { $gte: ["$rating", 4] },
                    1,
                    0
                ]
            }
        }
    }
}
  1. 计算好评率并再次筛选:在另一个$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 }
    }
}
  1. 按平均评分降序排列:最后使用$sort阶段按平均评分降序排列。
{
    $sort: {
        averageRating: -1
    }
}

性能瓶颈及优化措施

  1. 大数据量下$match筛选性能问题
    • 瓶颈:在超大数据量下,$match筛选操作可能会因为需要遍历大量文档而性能低下。
    • 优化:确保ratingreviewTime字段上有合适的索引。可以使用复合索引,例如createIndex({rating: 1, reviewTime: 1}),以加速筛选过程。
  2. $group阶段性能瓶颈
    • 瓶颈$group操作需要对数据进行分组,在大数据量时内存消耗大,且处理时间长。
    • 优化:如果数据量过大,可以考虑分阶段聚合。先在部分数据上进行本地聚合,然后再将这些聚合结果进行最终的全局聚合。另外,可以增加内存限制来提高$group操作的性能,但要注意服务器的实际内存情况。
  3. 排序性能问题
    • 瓶颈$sort操作在大数据量下,特别是当需要排序的数据量接近或超过内存大小时,性能会急剧下降。
    • 优化:在排序字段averageRating上创建索引createIndex({averageRating: -1})。并且如果可能,尽量减少参与排序的数据量,例如在排序前先进行筛选操作。