如何用Objection Relation Mapping实现OR条件的关联查询?
Objection.js实现OR条件关联JOIN的解决方案
要实现JOIN Records ON Accounts.id = Records.account_id OR Accounts.id = Records.from_account_id这种带OR条件的关联,不能直接在join.to中写OR表达式——因为Objection的默认from/to关联仅支持简单的等值匹配,无法解析OR逻辑。以下是两种可行的解决方法:
方法一:自定义关联的ON子句(推荐)
在Account模型的关联配置中,放弃使用from和to,改用join回调手动构建包含OR条件的ON子句:
const { Model } = require('objection'); const Record = require('./Record'); class Account extends Model { static get tableName() { return 'Accounts'; } static get relationMappings() { return { allRecords: { relation: Model.HasManyRelation, modelClass: Record, join: (joinBuilder) => { joinBuilder .on('Accounts.id', '=', 'Records.account_id') .orOn('Accounts.id', '=', 'Records.from_account_id'); } } }; } }
使用时直接通过关联字段查询即可:
const accounts = await Account.query().withGraphFetched('allRecords');
这会自动生成你需要的带OR条件的JOIN语句,返回的每个Account对象的allRecords字段会包含所有匹配的Record数据。
方法二:查询时手动添加自定义JOIN
如果不想修改模型的关联配置,也可以在查询阶段直接用joinRaw添加自定义JOIN逻辑,再手动整理结果:
const accountsWithRecords = await Account.query() .leftJoinRaw('LEFT JOIN Records ON Accounts.id = Records.account_id OR Accounts.id = Records.from_account_id') .select('Accounts.*', 'Records.id as record_id', 'Records.amount') // 按需选择字段 .groupBy('Accounts.id', 'Records.id') .then(results => { // 手动将同一Account的Records合并到数组中 const accountMap = new Map(); results.forEach(row => { const accountId = row.id; if (!accountMap.has(accountId)) { accountMap.set(accountId, { ...row, records: [] }); } if (row.record_id) { accountMap.get(accountId).records.push({ id: row.record_id, amount: row.amount }); } }); return Array.from(accountMap.values()); });
这种方式适合临时查询场景,但需要手动处理结果分组。
内容的提问来源于stack exchange,提问作者Yaroslav Buhaievskyi
相关产品推荐
相关产品推荐

