如何实现MongoDB查询指定用户不重复space的最新5条SpaceHistory记录?
如何调整MongoDB查询以返回不重复space字段的最多5条SpaceHistory记录?
需求回顾
你需要实现一个接口,返回指定用户的最多5条SpaceHistory记录,核心要求:
- 记录中的
space字段不重复 - 按
createdDate字段倒序排列(最新记录优先)
当前实现的问题
你现有的find查询只能按时间排序并返回所有匹配的记录,但无法实现space字段的去重——重复的space记录会被全部返回,完全不符合需求。
解决方案:使用MongoDB聚合管道
要同时实现「去重+保留最新记录+限制数量」的需求,普通查询做不到,我们需要用聚合管道来处理,具体实现如下:
聚合管道各阶段作用拆解
$match:先筛选出指定owner的记录,减少后续处理的数据量,提升效率$sort:按createdDate倒序排列,确保每个space的最新记录排在最前面$group:按space字段分组,每个组只保留第一条记录(也就是该space的最新记录),同时保留原文档的所有字段$sort:分组后结果顺序可能被打乱,再次按createdDate倒序保证最终结果的顺序正确$limit:限制最多返回5条结果$project(可选):重新映射字段,将分组生成的临时_id替换为原文档的_id,让返回结构和原查询保持一致
完整实现代码
SpaceHistory.aggregate([ // 第一步:筛选指定owner的记录 { $match: { owner: req.params.owner } }, // 第二步:按创建时间倒序,确保最新记录排在最前面 { $sort: { createdDate: -1 } }, // 第三步:按space分组,保留每组第一条(最新)的完整记录 { $group: { _id: "$space", originalId: { $first: "$_id" }, owner: { $first: "$owner" }, space: { $first: "$space" }, createdDate: { $first: "$createdDate" }, __v: { $first: "$__v" } } }, // 第四步:再次按创建时间倒序,保证结果顺序正确 { $sort: { createdDate: -1 } }, // 第五步:限制最多返回5条记录 { $limit: 5 }, // 第六步:重新映射字段,恢复原文档的_id结构(可选) { $project: { _id: "$originalId", owner: 1, space: 1, createdDate: 1, __v: 1 } } ]).exec(function(err, spaceHistory) { if (err) { return res.send(new errors.ServerError(err)); } // 聚合返回的是数组,判断长度为空更准确 if (spaceHistory.length === 0) { return res.send(new errors.ResourceNotFoundError('Space History Not Found')); } res.send(spaceHistory); });
针对你的示例数据的效果
用你提供的示例数据测试,这个查询会返回:
space: "5c427de8cbf49d4b7cfe8115"的最新记录(createdDate: 2019-01-19T01:50:38.664Z)space: "5c427d3acbf49d4b7cfe8114"的记录(createdDate: 2019-01-19T01:49:09.875Z)
总共2条记录,完全符合「去重+按时间倒序」的要求。
内容的提问来源于stack exchange,提问作者Nicolas Kao
相关产品推荐
相关产品推荐

