如何用Sequelize实现双LEFT OUTER JOIN获取关联用户与好友完整数据
解决Sequelize双LEFT OUTER JOIN关联同一张表的问题
嘿,我之前刚踩过这个坑!要同时拉取好友关系里双方的完整用户数据,核心是给同一张表的两次关联设置不同的别名,这样Sequelize才能区分开两个JOIN的对象。下面一步步来:
第一步:先正确定义模型关联
首先你需要在Friends模型里,和Users表建立两个独立的关联,分别对应userId(发起好友关系的用户)和idFriend(被关联的好友),一定要给每个关联起独特的别名:
// 假设你的Users模型叫User,Friends模型叫Friend const User = require('./user.model'); const Friend = require('./friend.model'); // 关联1:Friend表的userId关联User表的id,别名为'initiator'(发起者) Friend.belongsTo(User, { foreignKey: 'userId', as: 'initiator', onDelete: 'CASCADE' }); // 关联2:Friend表的idFriend关联User表的id,别名为'friend'(好友) Friend.belongsTo(User, { foreignKey: 'idFriend', as: 'friend', onDelete: 'CASCADE' });
第二步:编写带双LEFT JOIN的查询
接下来就可以用findAll方法,通过include同时引入这两个关联,再加上筛选条件(用户ID=23,不管是发起者还是好友):
const { Op } = require('sequelize'); // Sequelize v6+ 需要单独引入Op async function getFriendshipsWithUsers(userId) { return await Friend.findAll({ where: { [Op.or]: [ { userId: userId }, { idFriend: userId } ] }, // 同时包含两个关联的用户数据 include: [ { model: User, as: 'initiator', attributes: ['id', 'username', 'email'] // 指定要返回的字段,也可以用exclude排除不需要的 }, { model: User, as: 'friend', attributes: ['id', 'username', 'email'] } ], raw: false, // 保持Sequelize实例格式,想要纯JSON可以设为true nest: true // 把关联的数据嵌套到对应的别名字段下,结构更清晰 }); } // 调用示例:查询用户23的所有好友关系及双方信息 const result = await getFriendshipsWithUsers(23); console.log(result);
关键注意点
- 别名
as必须和关联定义、查询时的include里的as完全一致,否则Sequelize会找不到关联 belongsTo默认生成的就是LEFT OUTER JOIN,不需要额外配置- 如果是Sequelize v5及以下版本,
Op的引入方式是const Op = Sequelize.Op,记得调整
这样返回的结果里,每条好友记录都会包含initiator和friend两个对象,分别对应双方的完整用户数据啦!
内容的提问来源于stack exchange,提问作者tetar
相关产品推荐
相关产品推荐

