MongoDB聚合如何限制$match中$in对应每个facilityId仅返回4条最新文件记录
问题原因说明
- 直接用全局
$limit只能限制总返回条数,无法实现分组限流。 - 你之前遇到的
Bad projection specification报错,是因为MongoDB投影规则不允许在排除模式(仅指定某个字段设为0不返回)下同时新增/修改计算字段,$slice属于计算字段操作,因此和file:0的排除规则冲突。 - 你原代码里
$sort: { createdAt: 1 }是按创建时间升序排列,返回的是最早创建的记录,要获取最新创建的需要改为降序-1。
正确聚合查询代码
const files = await File.aggregate([ // 过滤目标facilityId的所有记录,缩小数据集 { $match: { facilityId: { $in: facilities } } }, // 按创建时间倒序,保证最新记录排在分组的最前面 { $sort: { createdAt: -1 } }, // 按facilityId分组,同组所有文档存入临时数组 { $group: { _id: "$facilityId", docs: { $push: "$$ROOT" } } }, // 截取每个分组前4条,即当前facilityId最新的4条记录 { $project: { docs: { $slice: ["$docs", 4] } } }, // 拆分临时数组为单条独立文档 { $unwind: "$docs" }, // 将文档内容恢复为根级结构 { $replaceRoot: { newRoot: "$docs" } }, // 排除不需要的file字段 { $project: { file: 0 } } ])
性能优化方案
如果你的数据集较大,分组时$push整个文档会占用额外内存,可以在分组阶段就指定需要返回的字段,跳过file字段,省略最后一步的排除投影,性能更好:
const files = await File.aggregate([ { $match: { facilityId: { $in: facilities } } }, { $sort: { createdAt: -1 } }, { $group: { _id: "$facilityId", docs: { $push: { _id: "$_id", name: "$name", userId: "$userId", facilityId: "$facilityId", patientId: "$patientId", type: "$type", accessed: "$accessed", sent: "$sent", createdAt: "$createdAt", updatedAt: "$updatedAt" } } } }, { $project: { docs: { $slice: ["$docs", 4] } } }, { $unwind: "$docs" }, { $replaceRoot: { newRoot: "$docs" } } ])
内容的提问来源于stack exchange,提问作者Sylvain Djsick
相关产品推荐
相关产品推荐

