MST

星途 面试题库

面试题:MongoDB聚合框架复杂表达式应用

假设你有一个存储用户订单信息的集合,文档结构包含用户ID(userId)、订单金额(amount)、订单日期(orderDate)。要求使用聚合框架,查询出每个月订单金额总和排名前三的用户,需要展示用户ID、月份及该月订单总金额。请写出对应的聚合管道表达式,并解释每一步的作用。
15.7万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

以下以MongoDB为例,给出聚合管道表达式及解释:

[
    // 步骤1:提取订单日期中的月份
    {
        $addFields: {
            month: { $month: "$orderDate" }
        }
    },
    // 步骤2:按用户ID和月份分组,计算每个用户每个月的订单总金额
    {
        $group: {
            _id: { userId: "$userId", month: "$month" },
            totalAmount: { $sum: "$amount" }
        }
    },
    // 步骤3:展开分组后的文档,将_id中的字段提升到顶级
    {
        $unwind: {
            path: "$_id"
        }
    },
    // 步骤4:重命名字段
    {
        $project: {
            userId: "$_id.userId",
            month: "$_id.month",
            totalAmount: 1,
            _id: 0
        }
    },
    // 步骤5:按月份和订单总金额降序排序
    {
        $sort: {
            month: 1,
            totalAmount: -1
        }
    },
    // 步骤6:按月份分组,保留每个月订单总金额排名前三的用户
    {
        $group: {
            _id: "$month",
            topUsers: {
                $push: {
                    userId: "$userId",
                    totalAmount: "$totalAmount"
                }
            }
        }
    },
    // 步骤7:展开每个月的前三个用户
    {
        $unwind: {
            path: "$topUsers",
            limit: 3
        }
    },
    // 步骤8:重命名字段,整理输出格式
    {
        $project: {
            month: "$_id",
            userId: "$topUsers.userId",
            totalAmount: "$topUsers.totalAmount",
            _id: 0
        }
    }
]
  • 步骤1:$addFields:使用$month操作符从orderDate字段中提取月份,并将其作为新字段month添加到文档中。
  • 步骤2:$group:按userIdmonth进行分组,使用$sum操作符计算每个用户每个月的订单总金额totalAmount
  • 步骤3:$unwind:将_id字段展开,使userIdmonth成为顶级字段,方便后续操作。
  • 步骤4:$project:重命名字段,保留userIdmonthtotalAmount字段,去除_id字段。
  • 步骤5:$sort:按month升序和totalAmount降序排序,以便后续获取每个月订单总金额排名靠前的用户。
  • 步骤6:$group:再次按month分组,使用$push操作符将每个月的用户信息(userIdtotalAmount)存储到topUsers数组中,每个月只保留排名前三的用户。
  • 步骤7:$unwind:展开topUsers数组,每个文档对应一个用户信息,limit: 3确保每个月只展开前三个用户。
  • 步骤8:$project:重命名字段,整理输出格式,最终输出用户ID、月份及该月订单总金额。