如何编写带嵌套关联where子句的Sequelize查询语句
Sequelize 查询指定用户名下所有账户全量交易记录实现方案
前置检查:确认模型关联配置
要实现跨三表的关联查询,首先要保证三个模型的关联关系已经正确注册:
- 用户(User)和账户(Account)是一对多关系:
User.hasMany(Account, { foreignKey: 'userId' })Account.belongsTo(User, { foreignKey: 'userId' })
- 账户(Account)和交易记录(Transaction)是一对多关系:
Account.hasMany(Transaction, { foreignKey: 'accountId' })Transaction.belongsTo(Account, { foreignKey: 'accountId' })
推荐写法:直接从交易表出发关联查询
如果最终需要直接拿到扁平化的交易记录列表,优先从Transaction模型发起查询,通过两层嵌套关联过滤目标用户,性能更好,不需要额外做数据拍平:
const { Op } = require('sequelize'); // 替换为实际需要查询的用户ID const TARGET_USER_ID = 1; const allUserTransactions = await Transaction.findAll({ // 可在此处添加交易本身的筛选条件,比如按时间、金额、类型过滤 // where: { // createTime: { // [Op.gte]: new Date('2024-01-01') // }, // type: 'expense' // }, include: [ { model: Account, required: true, // 内连接,自动过滤无有效关联账户的孤儿交易 // 不需要返回账户字段时保留attributes: [],需要的话可以自定义要返回的账户字段 attributes: ['id', 'accountName', 'type'], include: [ { model: User, required: true, where: { id: TARGET_USER_ID }, attributes: [] // 不需要返回用户信息,减少冗余字段查询 } ] } ] });
可选写法:从用户实例出发嵌套查询
如果你已经拿到了目标用户的Sequelize实例,也可以从User模型出发嵌套查询,不过返回结果是「用户-账户列表-每个账户下的交易列表」的层级结构,需要手动拍平得到全量交易:
const targetUser = await User.findByPk(TARGET_USER_ID, { include: [ { model: Account, // 自定义返回的账户字段 attributes: ['id', 'accountName'], include: [ { model: Transaction, // 自定义返回的交易字段 attributes: ['id', 'amount', 'type', 'createTime', 'remark'] } ] } ] }); // 手动拍平得到所有交易记录 const allUserTransactions = targetUser.Accounts.flatMap(account => account.Transactions);
注意事项
required: true对应SQL的INNER JOIN,只会保留完全满足关联条件的数据;如果需要保留关联不到对应账户/用户的记录,可以将该值改为false,对应LEFT JOIN- 嵌套查询时可以通过
attributes字段自定义每层关联要返回的字段,避免查出冗余数据 - 如果需要分页查询交易记录,不要从User/Account模型出发做嵌套include查询,会导致分页计数不准,必须使用第一种从Transaction模型出发的写法
内容的提问来源于stack exchange,提问作者Ramiro Estevez
相关产品推荐
相关产品推荐

