如何用Mongoose按分类限制查询结果,每个分类最多5条
实现每个分类最多返回5条记录的方案
完全可行!这是MongoDB里很常见的需求,你可以通过聚合框架来轻松实现。下面给你两种常用的方案,按需选择:
方案1:经典分组+切片(兼容所有MongoDB版本)
这种方法通过先按displayInCategories分组,把同分类的文档收集到数组里,再对数组切片只保留前5条,最后展开数组得到结果:
db.yourCollection.aggregate([ // 按分类分组,将同分类的文档存入数组 { $group: { _id: "$displayInCategories", docs: { $push: "$$ROOT" } // 保留完整文档,也可以指定需要的字段 } }, // 对每个分类的文档数组切片,只保留前5条 { $project: { _id: 0, displayInCategories: "$_id", docs: { $slice: ["$docs", 5] } } }, // 展开切片后的数组,恢复成单文档格式 { $unwind: "$docs" }, // 可选:将文档结构恢复成原始格式(如果需要) { $replaceRoot: { newRoot: "$docs" } } ])
方案2:窗口函数(MongoDB 5.0+ 推荐使用)
如果你的MongoDB版本是5.0及以上,用窗口函数会更高效,尤其是数据量很大的时候,不需要先把所有同分类文档都存入数组:
db.yourCollection.aggregate([ // 为每个分类的文档添加序号,按你需要的排序规则(比如创建时间)排序 { $setWindowFields: { partitionBy: "$displayInCategories", sortBy: { createdAt: -1 }, // 这里可以替换成你需要的排序字段 output: { rowNumber: { $rowNumber: {} } } } }, // 只保留每个分类中序号≤5的文档 { $match: { rowNumber: { $lte: 5 } } }, // 可选:移除添加的rowNumber字段 { $project: { rowNumber: 0 } } ])
注意事项
- 如果你需要按特定规则排序每个分类下的文档,记得在对应的步骤里添加排序逻辑:窗口函数方案直接在
sortBy里指定;经典方案需要在$group前先加$sort阶段。 - 经典方案在处理超大规模数据时,可能会因为
$push生成过大的数组而影响性能,这时候优先选择窗口函数方案。
内容的提问来源于stack exchange,提问作者Yashaswi Maharshi
相关产品推荐
相关产品推荐

