场景
2025年02月28日
一、电商平台订单统计
1.1 认识
电商平台订单统计: 设计一个 MongoDB
聚合查询,统计某个时间段内,每个用户的订单总数、总金额,并按订单金额从高到低排序。
1.2 实现
db.orders.aggregate([
{ $match: { orderDate: { $gte: ISODate("2024-01-01"), $lt: ISODate("2024-12-31") } } },
{ $group: {
_id: "$userId",
totalAmount: { $sum: "$orderAmount" },
orderCount: { $sum: 1 }
}},
{ $sort: { totalAmount: -1 } }
])
-
解释
$match
在管道中的位置是否会影响性能。 -
询问
$group
之后数据如何排序,以及MongoDB
是否会对_id
自动排序。 -
询问如果
orderAmount
为空或缺失,该查询会如何表现?如何处理?
二、社交平台用户点赞查询
2.1 认识
社交平台用户点赞查询: 设计一个 MongoDB
聚合查询,查询某个用户点赞过的帖子信息,包含帖子的作者信息(假设 likes
集合存储了 userId
和 postId
)。
2.2 实现
db.likes.aggregate([
{ $match: { userId: ObjectId("1234567890abcdef12345678") } },
{ $lookup: {
from: "posts",
localField: "postId",
foreignField: "_id",
as: "postInfo"
}},
{ $unwind: "$postInfo" },
{ $lookup: {
from: "users",
localField: "postInfo.authorId",
foreignField: "_id",
as: "authorInfo"
}},
{ $unwind: "$authorInfo" },
{ $project: {
_id: 0,
postTitle: "$postInfo.title",
authorName: "$authorInfo.name",
likedAt: "$createdAt"
}}
])
-
解释
$lookup
的原理,以及MongoDB
为何不擅长JOIN
。 -
询问
$unwind
在这个查询中的作用,以及$lookup
结果是数组时如何处理? -
让候选人优化该查询,例如添加索引、避免
$unwind
过多导致性能问题。
三、统计订单总数和订单金额平均值
3.1 认识
统计订单总数和订单金额平均值: 使用 $facet
进行并行统计, 同时返回 订单总数 和 订单金额平均值,而不是分两次查询数据库。
3.2 实现
db.orders.aggregate([
{ $facet: {
orderStats: [
{ $group: { _id: null, totalOrders: { $sum: 1 } } }
],
amountStats: [
{ $group: { _id: null, avgAmount: { $avg: "$orderAmount" } } }
]
}}
])