Mongoose自定义排序:按用户已读/未读排序故事列表
解决Mongoose中按未读状态自定义排序的问题
你之前的代码编译错误,核心原因是Mongoose的sort()方法不支持为字段传入自定义函数作为排序规则——sort的对象参数中,字段值只能是1/-1或'asc'/'desc',无法直接通过函数判断数组包含关系来排序。
以下是两种可行的解决方案:
方案一:数据库层面聚合排序(推荐,适合大数据量)
通过MongoDB聚合管道先标记未读状态,再按规则排序,所有逻辑在数据库端完成,效率更高:
const totalStories = await this.Story.aggregate([ // 添加临时字段isUnread:未读标记为1,已读标记为0 { $addFields: { isUnread: { $cond: { if: { $not: { $in: [userid, '$seenBy'] } }, then: 1, else: 0 } } } }, // 排序规则:未读故事在前,同状态下按更新时间降序 { $sort: { isUnread: -1, updatedAt: -1 } }, // 可选:移除临时字段,不影响业务逻辑可省略 { $project: { isUnread: 0 } } ]); // 若需要关联其他文档(替代原populate逻辑),可在聚合中加入$lookup // 示例:假设原populateStory()是关联author字段到users集合 // { // $lookup: { // from: 'users', // localField: 'author', // foreignField: '_id', // as: 'author' // } // }
方案二:内存中排序(适合小数据量)
先查询所有数据并完成关联,再在Node.js内存中通过自定义函数排序:
// 先获取所有故事并完成关联 let totalStories = await this.Story.find({}) .populate(this.populateStory()); // 自定义排序逻辑 totalStories.sort((storyA, storyB) => { const aUnread = !storyA.seenBy.includes(userid); const bUnread = !storyB.seenBy.includes(userid); // 未读故事优先排前 if (aUnread && !bUnread) return -1; if (!aUnread && bUnread) return 1; // 同状态下按更新时间降序 return storyB.updatedAt.getTime() - storyA.updatedAt.getTime(); });
内容的提问来源于stack exchange,提问作者Vats Patel
相关产品推荐
相关产品推荐

