sequelize模型关联_Sequelize 中文API文档-3. 模型(表)之间的关系/关联

模型(Model)之间存在各种各样的关系,如:一对一(One-To-One )、一对多(One-To-Many)等。模型间的关系本质上是对其代表的数据库中表之间的关系描述,通过这些关系可以实现数据库中表之间主/外键约束的创建。查询时也可以基于这些关系,生成在数据库中执行的连接查询或复合查询SQL语句。

1. 关系/关联的使用

Sequelize 中的模型存在多种关系。在一个User.hasOne(Project)形式的调用中,正在调用的模型User是源模型而做为参数被传入的模型是目标模型。

1.1 一对一(One-To-One)关联

一对一关联是由一个单一的外键,实现两个模型之间的精确关联。

BelongsTo - 属于

BelongsTo关联表示一对一关系的外键存在于源模型。

如,下例中Player是通过外键关联的Team的一部分:

var Player = this.sequelize.define('player', {/* attributes */})

, Team = this.sequelize.define('team', {/* attributes */});

Player.belongsTo(Team); // 会为Player添加一个teamId 属性以保持与Team 主键的关系

外键

默认情况下,一个属于关系的外键将从目标模型的名称和主键名称生成。

默认命名使用驼峰式命名,而在源模型中添加了underscored: true配置,将使用蛇型命名。

var User = this.sequelize.define('user', {/* attributes */})

, Company = this.sequelize.define('company', {/* attributes */});

User.belongsTo(Company); // 会为user 添加 companyId 属性

var User = this.sequelize.define('user', {/* attributes */}, {underscored: true})

, Company = this.sequelize.define('company', {

uuid: {

type: Sequelize.UUID,

primaryKey: true

}

});

User.belongsTo(Company); // 会为user 添加 company_uuid 属性

在定义中使用as命名时,会将其做为目标模型的名称:

var User = this.sequelize.define('user', {/* attributes */})

, UserRole = this.sequelize.define('userRole', {/* attributes */});

User.belongsTo(UserRole, {as: 'role'}); // 会为 user添加 roleId 属性而不是 userRoleId

在任命情况下,使用使用了foreignKey选项,外键名都会使用此选项值。我可以在Sequelize 中像下面这样使用外键:

var User = this.sequelize.define('user', {/* attributes */})

, Company = this.sequelize.define('company', {/* attributes */});

User.belongsTo(Company, {foreignKey: 'fk_company'}); // 为User 添加fk_company 外键

目标键

目标键是位于目标模型上通过源模型外键列指向的列。默认情况下,目标键是会belongsTo关系中目标模型的主键。要使用自定义列,请用targetKey选项来指定:

var User = this.sequelize.define('user', {/* attributes */})

, Company = this.sequelize.define('company', {/* attributes */});

User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // 为User 添加 fk_companyname 目标键

HasOne - 拥有一个

HasOne关联表示一对一关系的外键存在于目标模型。

var User = sequelize.define('user', {/* ... */})

var Project = sequelize.define('project', {/* ... */})

// hasOne 关系

Project.hasOne(User)

/*

在这个示例中,hasOne会添加一个projectId 属性到User模型中

另外,Project.prototype 中会增加根据传入的第一个定义参数生成的访问器方法 getUser 和 setUser 置。

如果启用了underscore 设置,添加的属性会是 project_id 而不是 projectId.

外键会存在于users 表中

你同样可以自定义外键,如:你想使用一个已存在数据库:

*/

Project.hasOne(User, { foreignKey: 'initiator_id' })

/*

因为 Sequelize 会访问器使用模型名(定义时的第一个参数),

如果不使用这个名称,可以在hasOne 的选项中指定:

*/

Project.hasOne(User, { as: 'Initiator' })

// 这时会有 Project#getInitiator 和 Project#setInitiator

// 或者可以定义一些自引用

var Person = sequelize.define('person', { /* ... */})

Person.hasOne(Person, {as: 'Father'})

// 会为Person 增加一个FatherId 属性

// 同样可以自定义外键:

Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'})

// 会为Person 增加一个 DadId 属性

// 这两种情况下都会有以下两个方法:

Person#setFather

Person#getFather

// 如果想对一个表做两次连接查询:

Team.hasOne(Game, {as: 'HomeTeam', foreignKey : 'homeTeamId'});

Team.hasOne(Game, {as: 'AwayTeam', foreignKey : 'awayTeamId'});

Game.belongsTo(Team);

虽然被称为HasOne 关联,但大多数 1:1关系中通常会使用BelongsTo 关联,因为BelongsTo 会在源模型中添加外键,而HasOne 则会在目标模型中添加外键。

HasOne 与BelongsTo 的不同

在1:1 的关系中,可使用HasOne 或BelongsTo来定义。但它们的使用场景有所不同,下面通过一个例子来说明。

我们有两张表,会别关联到Player 和Team模型,定义如下:

var Player = this.sequelize.define('player', {/* attributes */})

, Team = this.sequelize.define('team', {/* attributes */});

在Sequelize 中我们可以源和目标模型的形式将二者建立联系。如将Player 做为源模型,而将Team做为目标模型:

Player.belongsTo(Team);

//Or

Player.hasOne(Team);

或Team 做为源模型,而将Player做为目标模型:

Team.belongsTo(Player);

//Or

Team.hasOne(Player);

HasOne 和 BelongsTo 插入外键的位置有所不同。HasOne 会向目标模型中插入关联键,而BelongsTo 会向源模型中插入关联键。

一个演示HasOne 和 BelongsTo使用的示例:

var Player = this.sequelize.define('player', {/* attributes */})

, Coach = this.sequelize.define('coach', {/* attributes */})

, Team = this.sequelize.define('team', {/* attributes */});

假设Player模型通过teamId列与其团队建立联系,每个团队的教练Coach信息通过coachId列存储。在这些 1:1 场景中需要以不同的方式建立关系,因为模型外键的存储位置不同。

当信息关联是存在于当前源模型时,我们可以使用belongsTo。在上面示例中,Player适合使用belongsTo,因为它有teamId列。

Player.belongsTo(Team) // `teamId` 会添加到 Player / 源模型

当信息关联是存在于当前目标模型时,我们可以使用hasOne。在上面示例中,Coach适合使用hasOne,因为model模型中存储了它的Coach信息的coachId字段。

Coach.hasOne(Team) // `coachId` 会添加到 Team / 目标模型

1.2 一对多(One-To-Many)关联

One-To-Many关联是指一个源模型连接多个目标模型。反之目标模型都会有一个明确的源。

var User = sequelize.define('user', {/* ... */})

var Project = sequelize.define('project', {/* ... */})

// 定义 hasMany 关联

Project.hasMany(User, {as: 'Workers'})

会向 User 中添加一个projectId或project_id属性。Project 的实例中会有访问器getWorkers 和 setWorkers。这是一种单向关联方式,如果两个模型间还有其它关联方式请参考下面的多对多关系。

1.3 多对多(Belongs-To-Many)关联

Belongs-To-Many 关联是指一个源模型连接多个目标模型。而且,目标模型也可以有多个相关的源。

Project.belongsToMany(User, {through: 'UserProject'});

User.belo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sequelize 是一个 Node.js ORM(Object-Relational Mapping) 框架,可以方便地进行数据库操作。在 Sequelize 中,关联查询可以通过定义模型之间关系来实现。下面是一个示例: 假设我们有两个模型:用户(User)和订单(Order),用户和订单之间是一对多的关系,即一个用户可以有多个订单。我们可以通过以下方式定义它们之间关系: ```javascript // User 模型 const User = sequelize.define('user', { name: DataTypes.STRING, age: DataTypes.INTEGER, }); // Order 模型 const Order = sequelize.define('order', { amount: DataTypes.FLOAT, }); // 关联关系 User.hasMany(Order); Order.belongsTo(User); ``` 上述代码中,我们通过 `hasMany` 和 `belongsTo` 方法来定义用户和订单之间关系。 接下来,我们可以使用 `include` 方法来进行关联查询: ```javascript User.findOne({ where: { id: 1 }, include: Order, }).then(user => { console.log(user.orders); // 打印该用户的所有订单 }); ``` 上述代码中,我们使用 `findOne` 方法查询 id 为 1 的用户,并通过 `include` 方法将该用户的所有订单一起查询出来。在查询结果中,用户对象上会有一个 `orders` 属性,该属性对应该用户的所有订单。 如果我们想在查询结果中包含订单的详细信息,可以进一步嵌套 `include` 方法: ```javascript User.findOne({ where: { id: 1 }, include: { model: Order, include: [Product], }, }).then(user => { console.log(user.orders[0].product); // 打印该用户的第一个订单的商品信息 }); ``` 上述代码中,我们通过嵌套 `include` 方法将订单和商品关联起来。在查询结果中,订单对象上会有一个 `product` 属性,该属性对应该订单所对应的商品信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值