如何在Mongoose中关联两个集合实现指定SQL查询,解决$lookup报错
MongoDB实现等价SQL的关联查询方案
原SQL逻辑拆解
你提供的SQL实际是查询满足以下两个条件任一的posts数据,最后按updated_at排序:
- posts的post_uploader字段等于当前用户ID
$user_id - posts的post_uploader字段属于当前用户关注的用户ID集合(即follow表中follow_follower_id等于
$user_id的所有follow_user_id)
报错原因说明
你之前的代码触发错误是因为$lookup的localField参数要求传入聚合主集合(posts集合)的字段名称,你直接传入了req.user.id这个具体值,不符合参数的类型要求。
推荐实现方案
方案1:两步查询法(性能最优,代码易维护)
适合绝大多数场景,逻辑和原SQL完全对齐,没有额外的聚合开销:
// 1. 查询当前用户关注的所有用户ID列表 const followedUserIdList = await followModel.distinct("follow_user_id", { follow_follower_id: req.user.id }); // 2. 合并当前用户ID和关注ID列表,查询符合要求的帖子 const resultPosts = await postModel.find({ post_uploader: { $in: [req.user.id, ...followedUserIdList] } }).sort({ updated_at: 1 }); // 升序传1,降序传-1,对应SQL默认升序排序规则
方案2:单聚合查询法(单次数据库请求)
适合需要在同一聚合流程中完成后续数据处理的场景:
const resultPosts = await postModel.aggregate([ // 关联follow集合,拉取当前用户的关注ID列表 { $lookup: { from: "follow", pipeline: [ { $match: { follow_follower_id: req.user.id } }, { $project: { follow_user_id: 1, _id: 0 } } ], as: "followedUserList" } }, // 提取纯关注ID数组 { $addFields: { followedIdArr: "$followedUserList.follow_user_id" } }, // 匹配符合条件的帖子 { $match: { $expr: { $or: [ { $eq: ["$post_uploader", req.user.id] }, { $in: ["$post_uploader", "$followedIdArr"] } ] } } }, // 按更新时间排序 { $sort: { updated_at: 1 } }, // 移除辅助字段 { $unset: ["followedUserList", "followedIdArr"] } ]);
注意事项
- 确保
post_uploader、follow_follower_id、follow_user_id三个字段的存储类型完全一致,比如同时为ObjectId类型或同时为字符串类型,避免匹配失效 - 如果需要最新的帖子排在最前,将
sort配置中的1改为-1即可,对应SQL的order by updated_at desc
内容的提问来源于stack exchange,提问作者Shubhajit Halder
相关产品推荐
相关产品推荐

