【问题标题】:Sequelize Typescript many-to-many specify 'through' Model attributesSequelize Typescript 多对多指定“通过”模型属性
【发布时间】:2022-03-01 00:11:45
【问题描述】:

我正在使用 sequelize-typescript 并尝试在获取用户时不将“通过”模型 (UserRole) 包含在多对多关联中。

当我得到一个用户时,JSON 看起来像这样:

{
    "id": 1,
    "email": "",
    "password": "",
    "isVerified": true,
    "verificationToken": "",
    "passwordResetToken": null,
    "createdAt": "2022-02-17T03:04:34.099Z",
    "updatedAt": "2022-02-17T03:05:20.754Z",
    "roles": [
        {
            "name": "SUPERADMIN",
            "UserRole": {
                "userId": 1,
                "roleId": 2,
                "createdAt": "2022-02-17T03:05:32.474Z",
                "updatedAt": "2022-02-17T03:05:32.474Z"
            }
        }
    ]
}

理想情况下,“roles”数组中的“UserRole”属性不会存在。或者,至少,我可以将名称从“UserRole”更改为“userRole”并删除“userId”和“roleId”属性。

我尝试在关联上指定“as”属性,为每个模型创建默认范围,但均无济于事。这个人sequelize-typescript many-to-many relationship model data with 也有类似的问题,但关心的是 HasMany 关系,我正在查看 BelongsToMany 关系。我的模型文件如下所示:

user.model.ts

import {
  Table,
  Column,
  Model,
  DataType,
  HasMany,
  BelongsToMany,
  DefaultScope,
} from "sequelize-typescript";
import { RefreshToken } from "./refreshToken.model";
import { Role } from "./role.model";
import { UserRole } from "./userRole";

@DefaultScope(() => ({
  include: [{ model: Role, attributes: ["name"], include: [] }],
}))
@Table({ tableName: "user", underscored: true })
class User extends Model {
  @Column(DataType.STRING)
  email!: string;

  @Column(DataType.STRING)
  password!: string;

  @Column(DataType.BOOLEAN)
  isVerified!: boolean;

  @Column(DataType.STRING)
  verificationToken!: string;

  @Column(DataType.STRING)
  passwordResetToken!: string;

  @HasMany(() => RefreshToken, {
    onDelete: "CASCADE",
  })
  refreshTokens!: RefreshToken[];

  @BelongsToMany(() => Role, {
    through: { model: () => UserRole },
  })
  roles!: Role[];

  @HasMany(() => UserRole, {
    onDelete: "CASCADE",
  })
  userRoles!: UserRole[];
}

export { User };

角色.model.ts

import {
  Table,
  Column,
  Model,
  DataType,
  HasMany,
  BelongsToMany,
} from "sequelize-typescript";
import { User } from "./user.model";
import { UserRole } from "./userRole";

@Table({ tableName: "role", underscored: true, timestamps: false })
class Role extends Model {
  @Column(DataType.STRING)
  name!: "ADMIN" | "SUPERADMIN";

  @BelongsToMany(() => User, {
    through: { model: () => UserRole },
  })
  users!: User[];

  @HasMany(() => UserRole, {
    onDelete: "CASCADE",
  })
  userRoles!: UserRole[];
}

export { Role };

userRole.model.ts

import {
  Table,
  Model,
  ForeignKey,
  BelongsTo,
  PrimaryKey,
  Column,
} from "sequelize-typescript";
import { Role } from "./role.model";
import { User } from "./user.model";

@Table({ tableName: "user_role", underscored: true })
class UserRole extends Model {
  @BelongsTo(() => User)
  user!: User;

  @ForeignKey(() => User)
  @PrimaryKey
  @Column
  userId!: number;

  @BelongsTo(() => Role)
  role!: Role;

  @ForeignKey(() => Role)
  @PrimaryKey
  @Column
  roleId!: number;
}

export { UserRole };

【问题讨论】:

  • 如果您在用户模型中使用 defaultScope,而不是 include: [],请尝试使用 through: { attributes: [] }。这是从表 (UserRole) 中删除任何属性作为响应。

标签: node.js typescript postgresql sequelize.js sequelize-typescript


【解决方案1】:

Emma 的回答是完全正确的,但我想提供一个小例子以使其更清楚。

当您包含多对多关系时,请直接包含最终表而不是直通表。 因此,如果您想与直通表进行交互,您必须从包含的“内部”进行。

通常你会这样做:

ModelA.findOne(where, include: [ModelB]);

但要访问直通模型,您必须这样做:

ModelA.findOne(where, include: [{model: ModelB, through: { attributes: ['']}}]);

在第二个示例中,我们告诉 Sequelize 执行 ManyToMany 关系,但不要从链接表中选择任何内容。 请注意,您可以将包含的所有属性(例如 where )放在此通过对象中。如果您尝试对直通模型进行一些操作,它会很有用。

另一个重要的一点:DefaultScopes 和 Scopes 可以与属性“属性”发生冲突。因此,最好选择其中一个,避免将它们混入一个请求中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 2018-09-08
    相关资源
    最近更新 更多