面试题答案
一键面试以下以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:按
userId
和month
进行分组,使用$sum
操作符计算每个用户每个月的订单总金额totalAmount
。 - 步骤3:$unwind:将
_id
字段展开,使userId
和month
成为顶级字段,方便后续操作。 - 步骤4:$project:重命名字段,保留
userId
、month
和totalAmount
字段,去除_id
字段。 - 步骤5:$sort:按
month
升序和totalAmount
降序排序,以便后续获取每个月订单总金额排名靠前的用户。 - 步骤6:$group:再次按
month
分组,使用$push
操作符将每个月的用户信息(userId
和totalAmount
)存储到topUsers
数组中,每个月只保留排名前三的用户。 - 步骤7:$unwind:展开
topUsers
数组,每个文档对应一个用户信息,limit: 3
确保每个月只展开前三个用户。 - 步骤8:$project:重命名字段,整理输出格式,最终输出用户ID、月份及该月订单总金额。