如何在 Sequelize 中急切加载多个外键,包括来自同一个 table 的 or 查询?
How do I eager load multiple foreign keys including an or query from the same table, in Sequelize?
我正在搜索 captain.entry_date 但我无法在 sequelize 模型中创建查询。
我的问题是任何船都存在船长,但 ship_captain.captain_id 有时为空。
对于这种情况,可以找到有关 route_id.
的船长
4 Tables :
ship, attributes:[id,name],
captain, attributes: [id, name, route_id, route_date]
ship_captain, attributes: [id, ship_id, route_id, captain_id]
route, attributes: [id, name]
select ship.name, c.name, c.entry_date
from ship left join ship_captain sc on ship.id = sc.ship_id
left join captain c on c.id = sc.captain_id or c.route_id = sc.route_id
到目前为止我尝试的是这个,但我不能在最后一个连接中使用 OR 运算符
Ship.hasMany(ShipCaptain, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Ship, {foreignKey: "ship_id"});
Captain.hasMany(ShipCaptain, {as: "ship_captain_by_id", foreignKey: "captain_id"});
ShipCaptain.belongsTo(Captain, {as: "ship_captain_by_route", foreignKey: "captain_id"});
Captain.hasMany(ShipCaptain, {as: "ship_captain_by_route", foreignKey: "route_id"});
ShipCaptain.belongsTo(Captain, {as: "ship_captain_by_route", foreignKey: "route_id"});
const options = {
attributes: ["name"],
include: [
{
model: Captain,
as: 'ship_captain_per_id',
required: false,
attributes: ["name","route_date"],
},
{
model: Captain,
as: 'ship_captain_per_route',
required: false,
attributes: ["name","route_date"],
}
],
}
const elements = await Ship.findAll(options);
这只是一个示例代码,可能是您想要重新排列数据库属性
但我尽力澄清问题。我无法更改客户数据库。
如果你真的只想使用一个协会通过captain_id
或route_id
获得一名船长而不是使用两个协会并自己映射它们那么你只需要定义一个协会hasOne
(而不是hasMany
)和总是使用on
选项通过[=18=加入ShipCaptain
和Captain
]:
Ship.hasMany(ShipCaptain, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Ship, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Captain, {as: "captain_by_captain", foreignKey: "captain_id"});
...
const options = {
attributes: ["name"],
include: [
{
model: ShipCaptain,
required: false,
include: [{
model: Captain,
required: false,
as: 'captain_by_captain',
attributes: ["name","route_date"],
on: {
[Op.or]: [{
id: Sequelize.col('ship_captain.captain_id'
}, {
id: Sequelize.col('ship_captain.route_id'
}]
}
}
]
},
],
}
const elements = await Ship.findAll(options);
我正在搜索 captain.entry_date 但我无法在 sequelize 模型中创建查询。
我的问题是任何船都存在船长,但 ship_captain.captain_id 有时为空。
对于这种情况,可以找到有关 route_id.
4 Tables :
ship, attributes:[id,name],
captain, attributes: [id, name, route_id, route_date]
ship_captain, attributes: [id, ship_id, route_id, captain_id]
route, attributes: [id, name]
select ship.name, c.name, c.entry_date
from ship left join ship_captain sc on ship.id = sc.ship_id
left join captain c on c.id = sc.captain_id or c.route_id = sc.route_id
到目前为止我尝试的是这个,但我不能在最后一个连接中使用 OR 运算符
Ship.hasMany(ShipCaptain, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Ship, {foreignKey: "ship_id"});
Captain.hasMany(ShipCaptain, {as: "ship_captain_by_id", foreignKey: "captain_id"});
ShipCaptain.belongsTo(Captain, {as: "ship_captain_by_route", foreignKey: "captain_id"});
Captain.hasMany(ShipCaptain, {as: "ship_captain_by_route", foreignKey: "route_id"});
ShipCaptain.belongsTo(Captain, {as: "ship_captain_by_route", foreignKey: "route_id"});
const options = {
attributes: ["name"],
include: [
{
model: Captain,
as: 'ship_captain_per_id',
required: false,
attributes: ["name","route_date"],
},
{
model: Captain,
as: 'ship_captain_per_route',
required: false,
attributes: ["name","route_date"],
}
],
}
const elements = await Ship.findAll(options);
这只是一个示例代码,可能是您想要重新排列数据库属性
但我尽力澄清问题。我无法更改客户数据库。
如果你真的只想使用一个协会通过captain_id
或route_id
获得一名船长而不是使用两个协会并自己映射它们那么你只需要定义一个协会hasOne
(而不是hasMany
)和总是使用on
选项通过[=18=加入ShipCaptain
和Captain
]:
Ship.hasMany(ShipCaptain, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Ship, {foreignKey: "ship_id"});
ShipCaptain.belongsTo(Captain, {as: "captain_by_captain", foreignKey: "captain_id"});
...
const options = {
attributes: ["name"],
include: [
{
model: ShipCaptain,
required: false,
include: [{
model: Captain,
required: false,
as: 'captain_by_captain',
attributes: ["name","route_date"],
on: {
[Op.or]: [{
id: Sequelize.col('ship_captain.captain_id'
}, {
id: Sequelize.col('ship_captain.route_id'
}]
}
}
]
},
],
}
const elements = await Ship.findAll(options);