了解 Sequelize 中的关联
Posted
技术标签:
【中文标题】了解 Sequelize 中的关联【英文标题】:Understanding Associations in Sequelize 【发布时间】:2019-10-01 00:27:58 【问题描述】:我正在尝试。我从现有的数据库表开始,因此某些字段可能与 Sequelize 中的默认值不匹配。我使用 Sequelizer 直接从数据库生成我的模型。 我习惯于编写查询,但现在我正在尝试了解像 Sequelize 这样的 ORM 是如何工作的。
这是我的模型。
models/user.js
module.exports = (sequelize, DataTypes) =>
const User = sequelize.define(
"User",
id:
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
field: "id"
,
username:
type: DataTypes.STRING(20),
allowNull: false,
field: "username"
,
fullname:
type: DataTypes.STRING(60),
allowNull: false,
field: "fullname"
,
createdat:
type: DataTypes.DATE,
allowNull: false,
field: "createdat"
,
updateat:
type: DataTypes.DATE,
allowNull: true,
field: "updateat"
,
deletedat:
type: DataTypes.DATE,
allowNull: true,
field: "deletedat"
,
tableName: "users",
timestamps: false
);
User.associate = function(models)
models.User.hasMany(models.Ticket),
as: "createdbyname", foreignKey: "createdby" ;
;
return User;
;
models/ticket.js
module.exports = (sequelize, DataTypes) =>
const Ticket = sequelize.define(
"Ticket",
id:
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
field: "id"
,
details:
type: DataTypes.STRING(45),
allowNull: true,
field: "details"
,
assignedto:
type: DataTypes.INTEGER(11),
allowNull: true,
field: "assignedto"
,
createdby:
type: DataTypes.INTEGER(11),
allowNull: true,
field: "createdby"
,
createdat:
type: DataTypes.DATE,
allowNull: false,
field: "createdat"
,
updatedat:
type: DataTypes.DATE,
allowNull: true,
field: "updatedat"
,
deletedat:
type: DataTypes.DATE,
allowNull: true,
field: "deletedat"
,
tableName: "tickets",
timestamps: false
);
Ticket.associate = function(models)
models.Ticket.belongsTo(models.User,
foreignKey: "createdby" );
;
return Ticket;
;
在我的路由处理程序中,我按如下方式调用 User.findAll:
models.User.findAll(
include: [models.Ticket]
)
我希望看到的结果是这样的查询:
SELECT
`User`.`id`,
`User`.`username`,
`User`.`fullname`,
`User`.`createdat`,
`User`.`updateat`,
`User`.`deletedat`,
`Tickets`.`id` AS `Tickets.id`,
`Tickets`.`details` AS `Tickets.details`,
`Tickets`.`assignedto` AS `Tickets.assignedto`,
`Tickets`.`createdby` AS `Tickets.createdby`,
`Tickets`.`createdat` AS `Tickets.createdat`,
`Tickets`.`updatedat` AS `Tickets.updatedat`,
`Tickets`.`deletedat` AS `Tickets.deletedat`
FROM
`users` AS `User`
LEFT OUTER JOIN
`tickets` AS `Tickets` ON `User`.`id` = `Tickets`.`createdby`
我在控制台中看到的查询是:
SELECT
`User`.`id`,
`User`.`username`,
`User`.`fullname`,
`User`.`createdat`,
`User`.`updateat`,
`User`.`deletedat`,
`Tickets`.`id` AS `Tickets.id`,
`Tickets`.`details` AS `Tickets.details`,
`Tickets`.`assignedto` AS `Tickets.assignedto`,
`Tickets`.`createdby` AS `Tickets.createdby`,
`Tickets`.`createdat` AS `Tickets.createdat`,
`Tickets`.`updatedat` AS `Tickets.updatedat`,
`Tickets`.`deletedat` AS `Tickets.deletedat`,
`Tickets`.`UserId` AS `Tickets.UserId`
FROM
`users` AS `User`
LEFT OUTER JOIN
`tickets` AS `Tickets` ON `User`.`id` = `Tickets`.`UserId`;
注意 LEFT OUTER JOIN 子句的区别。这会引发如下错误:
Unhandled rejection SequelizeDatabaseError: Unknown column 'Tickets.UserId' in 'field list'
我需要一些帮助来找出我哪里出错了。
【问题讨论】:
我发现这个线程很有用,原因与 brilang 相同,我为了给我指出正确的方向来定义模型中的关联。下一步是如何填充关系。我正在阅读有关 setUser 或 addUser 的文档,但没有一个有效。帮助或建议将不胜感激。 【参考方案1】:定义关联时,例如belongsTo
,您可以指定foreignKey
和targetKey
。 foreignKey
对应于源表中的字段(请记住,语法是 sourceModel.belongsTo(targetModel, options)
)。 targetKey
对应目标表中的字段。
在您的情况下,您在 models/ticket.js 文件中的关联有误,您使用了:
models.Ticket.belongsTo(models.User, foreignKey: "createdby" );
这里,foreignKey
引用源表 Ticket。因此,您告诉 Sequelize 将字段 createdBy
用于 Ticket
表,并将默认(主键)用于 User
表。由于createdBy
不存在于Ticket
中,Sequelize 会退回到使用Ticket.UserID
的默认情况。
要修复您的关联(和查询),您需要将您的 belongsTo
更新为以下内容:
models.Ticket.belongsTo(models.User, targetKey: "createdby" );
【讨论】:
谢谢。我得到了这个样本。我已经转移到其他图书馆,因为我正在试验和学习什么对我有用,什么对我没用。【参考方案2】: Plant.findAll(
include: Farm,
order: [['name', 'ASC']]
)
.then(data=>
res.send(data)
)
.catch(err =>
res.send(err)
console.log(err);
)
let arrQuery = [
queryInterface.addColumn('farms', 'dayPlayed' , Sequelize.STRING),
queryInterface.removeColumn('plants', 'dayPlayed' , Sequelize.STRING),
]
return Promise.all(arrQuery)
【讨论】:
一些文字解释会很有帮助,尤其是因为运行 sn-p 会产生错误以上是关于了解 Sequelize 中的关联的主要内容,如果未能解决你的问题,请参考以下文章