从多对多关系中获取结果

Getting results from a many-to-many relation

我正在尝试从 GraphQL 解析器中的多对多关系(用户和角色之间)获取结果,但我对 Sequelize 很陌生,不了解查询模型的正确方法.

这是我的用户模型:

module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('users', {
 id: {
  type: DataTypes.INTEGER(10).UNSIGNED,
  allowNull: false,
  primaryKey: true,
  autoIncrement: true
 },
 name: {
  type: DataTypes.STRING(50),
  allowNull: false
 },
 surname: {
  type: DataTypes.STRING(50),
  allowNull: false
 },
 email: {
  type: DataTypes.STRING(256),
  allowNull: false
 }
}, {
 tableName: 'users',
 timestamps: false,
});

User.associate = function (models) {
 User.belongsToMany(models.roles, {as: 'UserRoles', through: 'users_roles', foreignKey: 'user_id'})
};

return User
};

这是我的角色模型:

module.exports = function(sequelize, DataTypes) {
var Role = sequelize.define('roles', {
 id: {
  type: DataTypes.INTEGER(10).UNSIGNED,
  allowNull: false,
  primaryKey: true,
  autoIncrement: true
 },
 name: {
  type: DataTypes.STRING(50),
  allowNull: false
 }
}, {
 tableName: 'roles',
 timestamps: false,
});

Role.associate = function (models) {
 Role.belongsToMany(models.users, {through: 'users_roles', foreignKey: 'role_id'})
};

return Role
};

这是我加入的 table 模型:

module.exports = function(sequelize, DataTypes) {
 return sequelize.define('users_roles', {
  id: {
   type: DataTypes.INTEGER(10).UNSIGNED,
   allowNull: false,
   primaryKey: true,
   autoIncrement: true
  },
  user_id: {
   type: DataTypes.INTEGER(10).UNSIGNED,
   allowNull: false,
   references: {
    model: 'users',
    key: 'id'
   }
  },
  role_id: {
   type: DataTypes.INTEGER(10).UNSIGNED,
   allowNull: false,
   references: {
    model: 'roles',
    key: 'id'
   }
  }
 }, {
  tableName: 'users_roles',
  timestamps: false
 });
};

到目前为止,这是我的 GraphQL 定义:

import { gql } from 'apollo-server-express'
import * as db from '../database'

export const typeDefs = gql`
    extend type Query {
        users: [User]
        user(id: ID!): User
    }
    type User {
        id: ID!
        email: String
        name: String
        surname: String
        roles: [String]
    }
`

export const resolvers = {
    Query: {
        users: async () => db.users.findAll(),
        user: async (obj, args, context, info) => db.users.findByPk(args.id),
    },
    User: {
        roles: async (obj, args, context, info) => db.roles.findAll(), // wrong!!
    }
}

基本上我的问题是我不知道应该如何编写查询来获取分配给一个用户的所有角色的列表。

我最终想要得到的(如 User 类型定义中所示)是一个包含所有角色名称的字符串数组。

给定一个 User 实例,我们已经正确定义了与另一个模型的 HasManyBelongsToMany 关系,我们可以通过调用适当的我们实例上的方法。方法名称通常为 get[PLURAL_NAME_OF_MODEL](即 getRoles),但由于您为关系提供了 as 选项,因此该方法应为 getUserRoles。所以只要打电话就足够了:

return obj.getUserRoles()

请注意,您还可以 eager load 根解析器中的关联模型。在这种情况下,如果 as 选项与您的字段名称匹配(即 roles),您可以完全省略 roles 的解析器。如果您急于加载关联模型,但 as 与您的字段名称不匹配(如本例),那么您可以 return obj[WHATEVER_THE_AS_OPTION_IS](即 obj.UserRoles)。

编辑:由于 roles 是一个字符串列表而不是对象,我们需要做如下事情:

const roles = await obj.getUserRoles()
return roles.map(role => role.name)