MST

星途 面试题库

面试题:MongoDB find命令在海量数据下的优化与聚合应用

对于一个拥有数十亿条记录的MongoDB集合‘transactions’,文档结构为{‘transaction_id’:‘string’, ‘user_id’:‘string’, ‘amount’:‘number’, ‘timestamp’:‘date’}。现在要查询出每个用户最近一周内交易金额总和排名前10的用户信息(用户ID和交易总金额),在保证查询性能的前提下,如何使用find命令结合聚合操作来实现?请详细阐述查询策略、命令及可能涉及的性能优化措施。
43.4万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

查询策略

  1. 筛选最近一周的数据:利用$match阶段筛选出timestamp在最近一周内的文档。需要获取当前日期并减去一周的时间,以此作为筛选条件。
  2. 按用户ID分组并计算交易总金额:使用$group阶段,以user_id作为分组依据,计算每个用户的交易金额总和。
  3. 按交易总金额降序排序:通过$sort阶段,按照交易总金额进行降序排列。
  4. 取前10名:利用$limit阶段,只返回排名前10的用户信息。

命令

var oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);

db.transactions.aggregate([
    {
        $match: {
            timestamp: { $gte: oneWeekAgo }
        }
    },
    {
        $group: {
            _id: "$user_id",
            totalAmount: { $sum: "$amount" }
        }
    },
    {
        $sort: {
            totalAmount: -1
        }
    },
    {
        $limit: 10
    }
]);

性能优化措施

  1. 索引优化
    • timestamp字段上创建索引,加速$match阶段的筛选操作。例如:db.transactions.createIndex({timestamp: 1})
    • user_idamount字段上创建复合索引,对于$group阶段按user_id分组并计算amount总和可能有帮助,例如:db.transactions.createIndex({user_id: 1, amount: 1})
  2. 分区:考虑对集合进行分区,按时间(如按天、周等)分区,这样在查询最近一周数据时,可以减少需要扫描的数据量。
  3. 使用覆盖索引:如果查询结果只包含user_idtotalAmount,确保索引覆盖了这些字段,这样查询可以直接从索引中获取数据,避免回表操作,提高查询性能。