使用自定义连接表主键 Sequelize BelongsToMany
Posted
技术标签:
【中文标题】使用自定义连接表主键 Sequelize BelongsToMany【英文标题】:Sequelize BelongsToMany with custom join table primary key 【发布时间】:2017-05-22 13:44:15 【问题描述】:我有一个多对多的关系,中间有一个连接表。这些表是 Cookoff、Participant 和 CookoffParticipant。我应该提到我不允许 Sequelize 创建或修改我的表,我只是在映射我现有的关系。我需要帮助了解哪些关系选项告诉 sequelize 调用将连接表与主表相关联的外键。
据我了解,Sequelize 假定 CookoffID 和 ParticipantID 是 CookoffParticipant 上的复合主键。在我的情况下,我要求主键是我调用 CookoffParticipantID 的标识列,并在 CookoffParticipant 表中的 CookoffID、ParticipantID 对上创建唯一索引。
当我尝试通过查询 cookoffParticipant 表来获取烹饪和参与者数据时,Sequelize 使用了错误的键来完成连接。一定有一些简单的事情我没有做。下面是我的表结构和带有结果的查询。
烹饪台
var Cookoff = sequelize.define("Cookoff",
// Table columns
CookoffID:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
,
Title:
type: DataTypes.STRING,
allowNull: false
,
EventDate:
type: DataTypes.DATE,
allowNull: false
, _.extend(,
// Table settings
defaultTableSettings,
classMethods:
associate: function(models)
Cookoff.belongsToMany(models.Participant,
through:
model: models.CookoffParticipant
,
as: "Cookoffs",
foreignKey: "CookoffID",
otherKey: "ParticipantID"
);
));
参与者表
var Participant = sequelize.define("Participant",
// Table columns
ParticipantID:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
,
Name:
type: DataTypes.STRING(100),
allowNull: false
, _.extend(,
defaultTableSettings,
classMethods:
associate: function(models)
Participant.belongsToMany(models.Cookoff,
through:
model: models.CookoffParticipant
,
as: "Participants",
foreignKey: "ParticipantID",
otherKey: "CookoffID"
);
));
Cookoff 参与者表
var CookoffParticipant = sequelize.define("CookoffParticipant",
CookoffParticipantID:
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
,
CookoffID:
type: DataTypes.INTEGER,
allowNull: false,
references:
model: cookoff,
key: "CookoffID"
,
ParticipantID:
type: DataTypes.INTEGER,
allowNull: false,
references:
model: participant,
key: "ParticipantID"
, _.extend(
,
defaultTableSettings,
classMethods:
associate: function (models)
CookoffParticipant.hasOne(models.Cookoff, foreignKey: "CookoffID" );
CookoffParticipant.hasOne(models.Participant, foreignKey: "ParticipantID" );
));
我的查询
return cookoffParticpants.findOne(
where: CookoffID: cookoffID, ParticipantID: participantID ,
include: [
model: participants ,
model: cookoffs
]
);
生成的 SQL
SELECT
[CookoffParticipant].[CookoffParticipantID],
[CookoffParticipant].[CookoffID],
[CookoffParticipant].[ParticipantID],
[Participant].[ParticipantID] AS [Participant.ParticipantID],
[Participant].[Name] AS [Participant.Name],
[Cookoff].[CookoffID] AS [Cookoff.CookoffID],
[Cookoff].[Title] AS [Cookoff.Title],
[Cookoff].[EventDate] AS [Cookoff.EventDate]
FROM [CookoffParticipant] AS [CookoffParticipant]
LEFT OUTER JOIN [Participant] AS [Participant]
ON [CookoffParticipant].[CookoffParticipantID] = [Participant].[ParticipantID] -- This should be CookoffParticipant.ParticipantID
LEFT OUTER JOIN [Cookoff] AS [Cookoff]
ON [CookoffParticipant].[CookoffParticipantID] = [Cookoff].[CookoffID] -- This should be CookoffParticipant.CookoffID
WHERE [CookoffParticipant].[CookoffID] = 1
AND [CookoffParticipant].[ParticipantID] = 6
ORDER BY [CookoffParticipantID]
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY;
您可以看到 Sequelize 正在尝试在 Participant.ParticipantID 上加入 CookoffParticipant.CookoffParticipantID,其中应该是 CookoffParticipant.ParticipantID = Participant.ParticipantID 和 CookoffID 类似。我在这里做错了什么?
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:这是您正在寻找的非常好的discussion。他们很好地总结了这一点,说您应该同时定义一个直通表和声明belongsTo 引用的直通表。您的问题可能是您使用了hasOne
而不是belongsTo
。另外我认为你的as
键是向后的。
Cookoff.hasMany(Book, through: CookoffParticipant )
Participant.hasMany(User, through: CookoffParticipant )
CookoffParticipant.belongsTo(Cookoff)
CookoffParticipant.belongsTo(Participant)
这是我用来测试的代码。
Cookoff.js
module.exports = (sequelize, DataTypes) =>
var Cookoff = sequelize.define("Cookoff",
CookoffID:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
, _.extend(
,
classMethods:
associate: function(models)
Cookoff.belongsToMany(models.Participant,
through: models.CookoffParticipant,
foreignKey: "CookoffID",
otherKey: "ParticipantID"
);
));
return Cookoff;
;
参与者.js
module.exports = (sequelize, DataTypes) =>
var Participant = sequelize.define("Participant",
ParticipantID:
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
, _.extend(
,
classMethods:
associate: function(models)
Participant.belongsToMany(models.Cookoff,
through: models.CookoffParticipant,
foreignKey: "ParticipantID",
otherKey: "CookoffID"
);
));
return Participant;
;
CookoffParticipant.js
module.exports = (sequelize, DataTypes) =>
var CookoffParticipant = sequelize.define("CookoffParticipant",
CookoffParticipantID:
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
, _.extend(
,
classMethods:
associate: function(models)
CookoffParticipant.belongsTo(models.Cookoff, foreignKey: "CookoffID" );
CookoffParticipant.belongsTo(models.Participant, foreignKey: "ParticipantID" );
));
return CookoffParticipant;
;
test.js
const db = require('../db');
const Cookoff = db.Cookoff;
const Participant = db.Participant;
const CookoffParticipant = db.CookoffParticipant;
let cookoff,
participant;
Promise.all([
Cookoff.create(),
Participant.create()
]).then(([ _cookoff, _participant ]) =>
cookoff = _cookoff;
participant = _participant;
return cookoff.addParticipant(participant);
).then(() =>
return CookoffParticipant.findOne(
where: CookoffID: cookoff.CookoffID, ParticipantID: participant.ParticipantID ,
include: [ Cookoff, Participant ]
);
).then(cookoffParticipant =>
console.log(cookoffParticipant.toJSON());
);
【讨论】:
谢谢。关键错误是使用 hasOne 而不是 belongsTo。进行该开关立即解决了问题。以上是关于使用自定义连接表主键 Sequelize BelongsToMany的主要内容,如果未能解决你的问题,请参考以下文章