Sequelize 是一个基于 Promise 的 Node.js ORM,目前支持 Postgres、MySQL、SQLite 和 Microsoft SQL Server。它具有强大的事务支持,关联关系、读取和复制等功能。在阅读本文前,如果你对 Sequelize 还不了解,建议先阅读 Sequelize 快速入门 这篇文章。
数据模型中的表关系一般有三种:一对一、一对多、多对多。Sequelize 为开发者提供了清晰易用的接口来定义关系、进行表之间的操作。本文我们将介绍在 Sequelize 中如何定义一对一的表关系。
基本概念
Source & Target
我们首先从一个基本概念开始,你将会在大多数关联中使用 source 和 target 模型。 假设您正试图在两个模型之间添加关联。 这里我们在 User 和 Project 之间添加一个 hasOne 关联。1
2
3
4
5
6
7
8
9
10const User = sequelize.define('User', {
name: Sequelize.STRING,
email: Sequelize.STRING
});
const Project = sequelize.define('Project', {
name: Sequelize.STRING
});
User.hasOne(Project);
User 模型(函数被调用的模型)是 source 。 Project 模型(作为参数传递的模型)是 target 。
BelongsTo
BelongsTo 关联是在 source model 上存在一对一关系的外键的关联。
一个简单的例子是 Player 通过 player 的外键作为 Team 的一部分。1
2
3
4const Player = this.sequelize.define('player', {/* attributes */});
const Team = this.sequelize.define('team', {/* attributes */});
Player.belongsTo(Team); // 将向 Player 添加一个 teamId 属性以保存 Team 的主键值
默认情况下,将从目标模型名称和目标主键名称生成 belongsTo 关系的外键。默认的样式是 camelCase,但是如果源模型配置为 underscored: true ,那么将使用字段 snake_case 创建 foreignKey。比如:1
2
3
4
5
6
7
8
9
10const User = this.sequelize.define('user', {/* attributes */}, {underscored: true})
const Company = this.sequelize.define('company', {
uuid: {
type: Sequelize.UUID,
primaryKey: true
}
});
// 将用字段 company_uuid 添加 companyUuid 到 user
User.belongsTo(Company);
此外,默认外键可以用 foreignKey 选项覆盖。 当设置外键选项时,Sequelize 将使用设置的参数值:1
2
3
4const User = this.sequelize.define('user', {/* attributes */})
const Company = this.sequelize.define('company', {/* attributes */});
User.belongsTo(Company, { foreignKey: 'fk_company' }); // 将 fk_company 添加到 User
HasOne
HasOne 关联是在 target model 上存在一对一关系的外键的关联。1
2
3
4
5const User = sequelize.define('user', {/* ... */})
const Project = sequelize.define('project', {/* ... */})
// 单向关联
Project.hasOne(User)
以上示例中,hasOne 将向 User 模型添加一个 projectId 属性。此外,Project.prototype 将根据传递给定义的第一个参数获取 getUser 和 setUser 的方法。 如果启用了 underscore 样式,则添加的属性将是 project_id 而不是 projectId。外键将放在 users 表上。
你也可以定义外键,比如如果你已经有一个现有的数据库并且想要处理它:1Project.hasOne(User, { foreignKey: 'initiator_id' })
HasOne vs BelongsTo
在 Sequelize 1:1 关系中可以使用 HasOne 和 BelongsTo 进行设置,它们适用于不同的场景。
我们先来定义以下两个模型:1
2const Player = this.sequelize.define('player', {/* attributes *