Sequelize
  • Introduction
  • 写在前面的话
  • 第一章 搭建环境
  • 第二章 模型定义
    • 2.1 实例变量方法
    • 2.2 定义一个模型
    • 2.3 模型字段类型
    • 2.3 导入与配置
  • 第三章 模型关系
    • 3.1 属于
    • 3.2 包含
    • 3.3 一对多
    • 3.4 多对多
    • 3.5 多态一对多
    • 3.6 多态多对多
    • 3.7 关系嵌套
  • 第四章 模型查询
  • 第五章 查询范围 Scope (预定义查询条件)
  • 第六章 生命周期函数 Hook
  • 第七章 数据库迁移 Migrate
  • 第八章 根据 Table 生成 Model
Powered by GitBook
On this page
  • 实例
  • 1.新建 tag.ts 文件
  • 2.在 user.ts 添加关系代码
  • 3.在 index.ts 里面添加验证代码
  1. 第三章 模型关系

3.4 多对多

在如今的社会,我们非常喜欢给人打上标签,比如 颜值逆天、暖烘烘、高富帅等等。高富帅并不是某一个人的专利,一个人可以被别人打上多个标签,一个标签也可以打在多个人上面。这就是多对多关系。

声明多对多关系需要用到belongsToMany方法。

User.beblongsToMany(Tag, {through: 'user_tag'});
Tag.belongsToMany(User, {through: 'user_tag'});

在多对多关系的表结构中,无论我们把关系 id 存在双方的任何一个表中,会出现上一节所提到的使用Book.hasOne(User)声明关系,有数据冗余的问题,所以在多对多关系下的表结构需要第三个表来保存它们之间的关系。

而这第三张表,就是上面的 user_tag 。里面有一个 userId 和一个 tagId 字段。

实例

1.新建 tag.ts 文件

import Sequelize from 'sequelize';
import {UserAttributes, UserInstance} from './user';

export interface TagAttributes {
  name: string;
}

export interface TagInstance extends Sequelize.Instance<TagAttributes>, TagAttributes {
  id: number;

  getUsers: Sequelize.BelongsToManyGetAssociationsMixin<UserInstance>,
  addUsers: Sequelize.BelongsToManyAddAssociationsMixin<UserInstance, number, any>,
  addUser: Sequelize.BelongsToManyAddAssociationMixin<UserInstance, number, any>,
  setUser: Sequelize.BelongsToManySetAssociationsMixin<UserInstance, number, any>,
  countUsers: Sequelize.BelongsToManyCountAssociationsMixin,
  createUser: Sequelize.BelongsToManyCreateAssociationMixin<UserAttributes, UserInstance, any>,
  hasUser: Sequelize.BelongsToManyHasAssociationMixin<UserInstance, number>,
  hasUsers: Sequelize.BelongsToManyHasAssociationsMixin<UserInstance, number>,
  removeUser: Sequelize.BelongsToManyRemoveAssociationMixin<UserInstance, number>,
  removeUsers: Sequelize.BelongsToManyRemoveAssociationsMixin<UserInstance, number>,

}

export default function TagDefine(sequelize: Sequelize.Sequelize, dataTypes: Sequelize.DataTypes): Sequelize.Model<TagInstance, TagAttributes>  {
    const S = dataTypes;
    const Tag = sequelize.define<TagInstance, TagAttributes>('Tag', {
        name: S.STRING
    }, {
        timestamps: false
    });

    (Tag as any).associate = function(this: typeof Tag, models){
        this.belongsToMany(models.User, {through: 'user_tag'});
    }

    return Tag;
}

2.在 user.ts 添加关系代码

  getTags: Sequelize.BelongsToManyGetAssociationsMixin<TagInstance>,
  addTags: Sequelize.BelongsToManyAddAssociationsMixin<TagInstance, number, any>,
  addTag: Sequelize.BelongsToManyAddAssociationMixin<TagInstance, number, any>,
  setTag: Sequelize.BelongsToManySetAssociationsMixin<TagInstance, number, any>,
  countTags: Sequelize.BelongsToManyCountAssociationsMixin,
  createTag: Sequelize.BelongsToManyCreateAssociationMixin<TagAttributes, TagInstance, any>,
  hasTag: Sequelize.BelongsToManyHasAssociationMixin<TagInstance, number>,
  hasTags: Sequelize.BelongsToManyHasAssociationsMixin<TagInstance, number>,
  removeTag: Sequelize.BelongsToManyRemoveAssociationMixin<TagInstance, number>,
  removeTags: Sequelize.BelongsToManyRemoveAssociationsMixin<TagInstance, number>,
 (User as any).associate = function(this: typeof User,models){
   // this.hasOne(models.Book);
   this.hasMany(models.Book);
   this.belongsToMany(models.Tag, { through: 'user_tag'});
}

3.在 index.ts 里面添加验证代码

import TagDefined, {TagAttributes, TagInstance} from './tag';

const Tag = sequelize.import<TagInstance, TagAttributes>('./tag');

let user = await User.create({email:'belovedyogurt@gmail.com',name: 'yugo'})
await user.createTag({name: '萌新'}); // 为 yugo 添加一个标签

let tag = (await Tag.findAll())[0]; // 拿到 tag 表中第一条数据

const tagUser = (await tag.getUsers())[0]; // 拿到该标签关联的用户的第一个

console.log(user.id == tagUser.id); // 俩边查出来的 user 是否相等

运行之后可以得到一个 true ,说明逻辑正确。而且在数据库中也创建了user_tag关联表,完成以上代码运行之后便可看到数据库中已存数据。

Previous3.3 一对多Next3.5 多态一对多

Last updated 7 years ago