TypeORM中单查询获取订阅社区与用户的帖子时连接冲突问题
问题分析
你当前的SQL用了两个内连接,相当于要求帖子必须同时满足「属于用户订阅的社区」和「作者是用户订阅的用户」,这就把两类数据的交集查出来了,而不是你要的两类数据的并集,所以逻辑冲突。
解决方案
方案一:原生SQL用EXISTS实现OR逻辑
用两个EXISTS子查询分别判断两个条件,只要满足其中一个就返回帖子:
select p.* from post p where -- 条件1:帖子属于用户订阅的社区 exists ( select 1 from subsite s join subsite_follow f on f.subsite_id = s.id where s.slug = p.subsite_slug and f.user_id = $1 ) OR -- 条件2:帖子作者是用户订阅的用户 exists ( select 1 from user_following uf where uf.user_id_2 = p.author_id and uf.user_id_1 = $1 )
方案二:用UNION合并两个独立查询
如果两类帖子的结果集没有重复(或允许去重),可以用UNION合并两个查询:
-- 订阅社区的帖子 select p.* from post p join subsite s on p.subsite_slug = s.slug join subsite_follow f on f.subsite_id = s.id and f.user_id = $1 UNION -- 订阅用户的帖子 select p.* from post p join user_following uf on uf.user_id_2 = p.author_id and uf.user_id_1 = $1
- 若允许同一帖子因满足两个条件重复出现,用
UNION ALL替代UNION,性能更优。
方案三:TypeORM QueryBuilder写法
符合ORM使用习惯,便于维护:
// 方式1:基于EXISTS子查询 const posts = await getRepository(Post) .createQueryBuilder('p') .where( '(exists (select 1 from subsite s join subsite_follow f on f.subsite_id = s.id where s.slug = p.subsite_slug and f.user_id = :userId))', { userId: req.user.id } ) .orWhere( '(exists (select 1 from user_following uf where uf.user_id_2 = p.author_id and uf.user_id_1 = :userId))', { userId: req.user.id } ) .getMany(); // 方式2:左连接+条件判断 const posts = await getRepository(Post) .createQueryBuilder('p') .leftJoin('subsite', 's', 's.slug = p.subsite_slug') .leftJoin('subsite_follow', 'f', 'f.subsite_id = s.id and f.user_id = :userId') .leftJoin('user_following', 'uf', 'uf.user_id_2 = p.author_id and uf.user_id_1 = :userId') .where('f.id IS NOT NULL OR uf.id IS NOT NULL') .setParameter('userId', req.user.id) .distinct(true) // 去重,避免同一帖子满足双条件时重复返回 .getMany();
内容的提问来源于stack exchange,提问作者Free
相关产品推荐
相关产品推荐

