Mongoose聚合分组查询如何仅获取每个用户最新的MUTE禁言记录
解决方案
问题根因
你的原查询错误点在$group阶段的分组键设置,使用$sanctions._id作为分组标识会将每条独立的MUTE处罚拆分为独立分组,最终返回所有符合条件的禁言记录,无法实现按用户聚合的效果。
修正后的查询代码
场景1:仅需要返回用户信息 + 最新禁言到期时间
直接通过$max聚合函数取每个用户最大的到期时间即可:
await User.aggregate([ { $unwind: '$sanctions' }, { $match: { 'sanctions.type': 'MUTE' } }, { $group: { _id: '$_id', // 核心修改:按用户自身的唯一ID分组,确保每个用户对应一条结果 user: { $first: '$user' }, expiry: { $max: '$sanctions.expiry' } } }, // 可选:调整返回字段格式,和你预期的输出结构对齐 { $project: { _id: 1, user: 1, expiry: 1 } } ]).exec();
场景2:需要返回最新禁言的完整信息(如处罚自身ID等)
如果需要拿到最新到期禁言对应的其他字段,先排序再取每组第一条更稳妥:
await User.aggregate([ { $unwind: '$sanctions' }, { $match: { 'sanctions.type': 'MUTE' } }, // 同用户的处罚按到期时间倒序排列,最新的记录排在最前 { $sort: { '_id': 1, 'sanctions.expiry': -1 } }, { $group: { _id: '$_id', user: { $first: '$user' }, expiry: { $first: '$sanctions.expiry' }, sanctionId: { $first: '$sanctions._id' } // 按需保留处罚的ID字段 } } ]).exec();
逻辑说明
$unwind:将每个用户的sanctions数组展开,单条处罚对应一个独立文档$match:过滤掉非MUTE类型的处罚,降低后续计算开销$group:按用户自身的_id分组,确保每个用户仅返回一条聚合结果$sort:同用户的处罚按到期时间倒序排列后取首条,确保拿到的是最新的禁言记录
内容的提问来源于stack exchange,提问作者Alissia
相关产品推荐
相关产品推荐

