了解 Sequelize 中的关联
Understanding Associations in Sequelize
我正在尝试了解 Sequelize 中的关联。我从现有的数据库表开始,因此某些字段可能与 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'
我需要一些帮助来找出我哪里出错了。
定义关联时,如 belongsTo
,您可以指定 foreignKey
和 targetKey
。 foreignKey
对应于源中的字段 table(请记住,语法是 sourceModel.belongsTo(targetModel, options)
)。 targetKey
对应目标中的字段table.
在你的情况下,你在models/ticket.js文件中的关联有误,你使用了:
models.Ticket.belongsTo(models.User, { foreignKey: "createdby" });
此处,foreignKey
引用来源 table,Ticket。因此,您是在告诉 Sequelize 使用字段 createdBy
作为 Ticket
table,并使用默认值(主键)作为 User
table。由于 createdBy
不存在于 Ticket
中,Sequelize 回退到默认情况,它使用 Ticket.UserID
.
要修复您的关联(和查询),您需要将 belongsTo
更新为以下内容:
models.Ticket.belongsTo(models.User, { targetKey: "createdby" });
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)
我正在尝试了解 Sequelize 中的关联。我从现有的数据库表开始,因此某些字段可能与 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'
我需要一些帮助来找出我哪里出错了。
定义关联时,如 belongsTo
,您可以指定 foreignKey
和 targetKey
。 foreignKey
对应于源中的字段 table(请记住,语法是 sourceModel.belongsTo(targetModel, options)
)。 targetKey
对应目标中的字段table.
在你的情况下,你在models/ticket.js文件中的关联有误,你使用了:
models.Ticket.belongsTo(models.User, { foreignKey: "createdby" });
此处,foreignKey
引用来源 table,Ticket。因此,您是在告诉 Sequelize 使用字段 createdBy
作为 Ticket
table,并使用默认值(主键)作为 User
table。由于 createdBy
不存在于 Ticket
中,Sequelize 回退到默认情况,它使用 Ticket.UserID
.
要修复您的关联(和查询),您需要将 belongsTo
更新为以下内容:
models.Ticket.belongsTo(models.User, { targetKey: "createdby" });
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)