Sequelize - 使用连接表查询

Posted

技术标签:

【中文标题】Sequelize - 使用连接表查询【英文标题】:Sequelize - query with join table 【发布时间】:2019-01-27 19:55:24 【问题描述】:

我正在构建具有权限的基于角色的身份验证。我有以下表格: UsersGroupsGroupPermissionsPermissions

Users模特:

module.exports = (sequelize, DataTypes) => 
    var User = sequelize.define('User', 
        id: 
            primaryKey: true,
            type: DataTypes.UUID,
            defaultValue: DataTypes.UUIDV4,
        ,
        email: DataTypes.STRING,
        password: DataTypes.STRING,
    , );

    User.associate = function(models) 
        User.belongsTo(models.Group,  as: 'group', foreignKey: 'groupId' );
    ;

    return User;
;

Group模特:

module.exports = (sequelize, DataTypes) => 
    var Group = sequelize.define('Group', 
        id: 
            primaryKey: true,
            type: DataTypes.UUID,
            defaultValue: DataTypes.UUIDV4,
        ,
        name: DataTypes.STRING,
    , 
        timestamps: false,
    );

        Group.associate = function(models) 
        Group.hasMany(models.User,  foreignKey: 'groupId' );
    ;

    return Group;
;

GroupPermission模特:

    module.exports = (sequelize, DataTypes) => 
        var GroupPermission = sequelize.define('GroupPermission', 
            id: 
                primaryKey: true,
                type: DataTypes.UUID,
                defaultValue: DataTypes.UUIDV4,
            ,
            groupId: 
                type: DataTypes.UUID,
                allowNull: false,
            ,
            permissionId: 
                type: DataTypes.UUID,
                allowNull: false,
            
        , );

        GroupPermission.associate = function(models) 
        ;

        return GroupPermission;
    ;

Permission模特:

module.exports = (sequelize, DataTypes) => 
    var Permission = sequelize.define('Permission', 
        id: 
            primaryKey: true,
            type: DataTypes.UUID,
            defaultValue: DataTypes.UUIDV4,
        ,
        name: 
            type: DataTypes.STRING,
            unique: true,
            allowNull: false,
        ,
        level: 
            type: DataTypes.TINYINT,
            allowNull: false,
        
    , );

    Permission.associate = function(models) 
    ;

    return Permission;
;

这是我获取所有用户的方法:

getAll(req, res) 
    return User
        .findAll(
            include: [
                
                    model: Group,
                    as: 'group',
                ,
            ]
        )
        .then(users => res.status(201).send( users ))
        .catch(error => res.status(400).send(error));
,

这给了我:


    "users": [
        
            "id": "03c50380-3f05-4d8d-893f-408a179fb993",
            "email": "johndoe@gmail.com",
            "password": "$2b$10$fP3BR14iSZRHs/sYi0QAVuh8Zno60GO1dOKbN4K7GkOdVod2EENfC",
            "groupId": "c89ef57e-da09-42c1-bb09-0d988a35dd97",
            "group": 
                "id": "c89ef57e-da09-42c1-bb09-0d988a35dd97",
                "name": "Admin"
            
        
    ]

我也想在group 内或group 属性旁边有permissions,但我不知道我做错了什么——查询或关联。我省略了我正在努力找出关联的代码,以免让任何有兴趣帮助我的人感到困惑。

【问题讨论】:

【参考方案1】:

首先你必须关联 Permission 和 Group 模型。我想你想通过GroupPermission进行多对多通信

module.exports = (sequelize, DataTypes) => 
  var Group = sequelize.define('Group', 
    id: 
      primaryKey: true,
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
    ,
    name: DataTypes.STRING,
  , 
    timestamps: false,
  );

  Group.associate = function(models) 
    Group.hasMany(models.User,  foreignKey: 'groupId' );
    Group.belongsToMany(models.Permission,  as: 'permissions', through: models.GroupPermission, foreignKey: 'groupId', otherKey: 'permissionId' )
  ;

  return Group;
;

module.exports = (sequelize, DataTypes) => 
  var GroupPermission = sequelize.define('GroupPermission', 
    id: 
      primaryKey: true,
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
    ,
    groupId: 
      type: DataTypes.UUID,
      allowNull: false,
    ,
    permissionId: 
      type: DataTypes.UUID,
      allowNull: false,
    
  , );

  GroupPermission.associate = function(models) 
  ;

  return GroupPermission;
;

module.exports = (sequelize, DataTypes) => 
  var Permission = sequelize.define('Permission', 
    id: 
      primaryKey: true,
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
    ,
    name: 
      type: DataTypes.STRING,
      unique: true,
      allowNull: false,
    ,
    level: 
      type: DataTypes.TINYINT,
      allowNull: false,
    
  , );

  Permission.associate = function(models) 
    Permission.belongsToMany(models.Group,  through: models.GroupPermission, foreignKey: 'permissionId', otherKey: 'groupId' );
  ;

  return Permission;
;

那么你可以:

getAll(req, res) 
  return User
    .findAll(
      include: [
        
          model: Group,
          as: 'group',
          include: [
            model: Permission,
            as: 'permissions',
          ]
        ,
      ]
    )
    .then(users => res.status(201).send( users ))
    .catch(error => res.status(400).send(error));

我还没有测试过代码,但它应该会给你一些想法。

【讨论】:

以上是关于Sequelize - 使用连接表查询的主要内容,如果未能解决你的问题,请参考以下文章

在 sequelize 返回值中删除连接表数据

Sequelize ORM中连接表的条件

如何使用node.js控制sequelize中的内连接查询?

使用 sequelize 通过相同两个表之间的单独联结表进行查询

如何在 sequelize 中使用子查询来引用 self 表?

使用自定义连接表主键 Sequelize BelongsToMany