在 Sequelize 中创建关联以进行左连接
Create Association in Sequelize to do a Left Join
我想使用与此 SQL 代码相同的 Sequelize 进行左连接。
SELECT * FROM events LEFT JOIN zones ON event_tz=zid WHERE event_creator_fk=116;
我有两个 table:events
和 zones
(带有时区列表)。
在查询特定用户创建的所有事件时,我还想获取时区名称和有关 TZ 的其他详细信息。
我尽我所能通过查看示例代码、其他 Stack Overflow 问题和文档尝试了许多解决方案组合。该查询始终有效,但不进行任何连接。也就是说,它下面的代码总是 returns 事件列表,但没有来自 zones
table 的时区数据。生成的 SQL 是正确的,只是它没有 ...LEFT JOIN zones ON event_tz=zid...
部分。
下面的代码是错误的。详情见答案。
db.Event.findAll(
{ where: { event_creator_fk: someUserID } },
{ include: [{ model: db.Zone } ]}
);
如果我理解正确,在 sequelize 中添加 table 之间的关联会导致自动创建一个额外的列。这不是我想做的。我不希望 Sequelize 以任何方式修改 tables 或数据库。我想设置我的数据库,它是没有 Sequelize 的 tables。因此,我不调用sequelize.sync()
。不知道有没有办法按照我想要的方式设置关联。
模型定义
module.exports = function (sequelize, DataTypes) {
var Event = sequelize.define('Event', {
eid: {
type: DataTypes.INTEGER,
primaryKey: true
},
event_tz: {
type: DataTypes.INTEGER,
primaryKey: true,
references: "Zone",
referencesKey: "zid"
},
}, {
classMethods: {
associate: function (models) {
return models.Event.hasOne(models.Zone);
}
},
freezeTableName: true,
timestamps: false,
tableName: 'events'
}
);
return Event;
};
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Zone', {
zid: {
type: DataTypes.INTEGER,
primaryKey: true
}
}, {
classMethods: {
associate: function (models) {
return models.Zone.belongsTo(models.Event);
}
},
freezeTableName: true,
timestamps: false,
tableName: 'zones'
});
};
Table 定义
DROP TABLE IF EXISTS zones;
CREATE TABLE IF NOT EXISTS zones (
zid integer NOT NULL,
country_code character(2) NOT NULL,
zone_name text NOT NULL,
PRIMARY KEY (zid)
);
DROP TABLE IF EXISTS events;
CREATE TABLE IF NOT EXISTS events (
eid BIGSERIAL NOT NULL,
event_tz SERIAL NOT NULL,
PRIMARY KEY (eid),
FOREIGN KEY (event_tz)
REFERENCES zones(zid) MATCH FULL ON DELETE RESTRICT
);
你需要反转关联并告诉sequelize你的外键。 belongsTo 表示 'add the fk to this model':
models.Event.belongsTo(models.Zone, { foreignKey: 'event_tz');
models.Zone.hasOne(models.Event, { foreignKey: 'event_tz');
// or hasMany if this is 1:m
部分问题是我错误地使用了 findAll
方法。查询选项 where
和 include
应该作为同一对象的一部分包含在内。 findAll
的第一个参数是选项参数。有关详细信息,请参阅 here。正确的代码应该如下所示。
db.Event.findAll(
{
where: { event_creator_fk: someUserID },
include: [{ model: db.Zone } ]
},
);
我想使用与此 SQL 代码相同的 Sequelize 进行左连接。
SELECT * FROM events LEFT JOIN zones ON event_tz=zid WHERE event_creator_fk=116;
我有两个 table:events
和 zones
(带有时区列表)。
在查询特定用户创建的所有事件时,我还想获取时区名称和有关 TZ 的其他详细信息。
我尽我所能通过查看示例代码、其他 Stack Overflow 问题和文档尝试了许多解决方案组合。该查询始终有效,但不进行任何连接。也就是说,它下面的代码总是 returns 事件列表,但没有来自 zones
table 的时区数据。生成的 SQL 是正确的,只是它没有 ...LEFT JOIN zones ON event_tz=zid...
部分。
下面的代码是错误的。详情见答案。
db.Event.findAll(
{ where: { event_creator_fk: someUserID } },
{ include: [{ model: db.Zone } ]}
);
如果我理解正确,在 sequelize 中添加 table 之间的关联会导致自动创建一个额外的列。这不是我想做的。我不希望 Sequelize 以任何方式修改 tables 或数据库。我想设置我的数据库,它是没有 Sequelize 的 tables。因此,我不调用sequelize.sync()
。不知道有没有办法按照我想要的方式设置关联。
模型定义
module.exports = function (sequelize, DataTypes) {
var Event = sequelize.define('Event', {
eid: {
type: DataTypes.INTEGER,
primaryKey: true
},
event_tz: {
type: DataTypes.INTEGER,
primaryKey: true,
references: "Zone",
referencesKey: "zid"
},
}, {
classMethods: {
associate: function (models) {
return models.Event.hasOne(models.Zone);
}
},
freezeTableName: true,
timestamps: false,
tableName: 'events'
}
);
return Event;
};
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Zone', {
zid: {
type: DataTypes.INTEGER,
primaryKey: true
}
}, {
classMethods: {
associate: function (models) {
return models.Zone.belongsTo(models.Event);
}
},
freezeTableName: true,
timestamps: false,
tableName: 'zones'
});
};
Table 定义
DROP TABLE IF EXISTS zones;
CREATE TABLE IF NOT EXISTS zones (
zid integer NOT NULL,
country_code character(2) NOT NULL,
zone_name text NOT NULL,
PRIMARY KEY (zid)
);
DROP TABLE IF EXISTS events;
CREATE TABLE IF NOT EXISTS events (
eid BIGSERIAL NOT NULL,
event_tz SERIAL NOT NULL,
PRIMARY KEY (eid),
FOREIGN KEY (event_tz)
REFERENCES zones(zid) MATCH FULL ON DELETE RESTRICT
);
你需要反转关联并告诉sequelize你的外键。 belongsTo 表示 'add the fk to this model':
models.Event.belongsTo(models.Zone, { foreignKey: 'event_tz');
models.Zone.hasOne(models.Event, { foreignKey: 'event_tz');
// or hasMany if this is 1:m
部分问题是我错误地使用了 findAll
方法。查询选项 where
和 include
应该作为同一对象的一部分包含在内。 findAll
的第一个参数是选项参数。有关详细信息,请参阅 here。正确的代码应该如下所示。
db.Event.findAll(
{
where: { event_creator_fk: someUserID },
include: [{ model: db.Zone } ]
},
);