Home > Net >  Sequelize a one-to-many relationship. how to create correctly?
Sequelize a one-to-many relationship. how to create correctly?

Time:03-12

I'm learning databases, trying to create a user and his two-factor authentication codes. Where one User can have multiple TwoFa

And so, there are 2 tables, User and TwoFa

user.ts

export interface IUser {
  id: string;
  email: string;
  password: string;
  twoFa: boolean; // Это флаг, включена ли двухфакторка
}

export interface IUserInstance
  extends Model<IUser, Omit<IUser, "id" | "twoFa">>,
    IUser,
    IDateAt {}

export const User = sequelize.define<IUserInstance>(
  "User",
  {
    id: {
      type: DataTypes.UUID,
      primaryKey: true,
      defaultValue: DataTypes.UUIDV4,
    },
    email: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false,
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    twoFa: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    },
  }
);

twoFa.ts

interface ITwoFa {
  id: string;
  ua: string;
}

export interface ITwoFaInstance
  extends Model<ITwoFa, Omit<ITwoFa, "id">>,
    ITwoFa {}

export const TwoFa = sequelize.define<ITwoFaInstance>(
  "TwoFa",
  {
    id: {
      type: DataTypes.UUID,
      primaryKey: true,
      defaultValue: DataTypes.UUIDV4,
    },
    ua: {
      type: DataTypes.STRING,
      allowNull: false,
    }
  }
);

Also a file with associations

User.hasMany(TwoFa, {
  as: "twoFaCodes",
  onDelete: "CASCADE",
  onUpdate: "CASCADE",
});
TwoFa.belongsTo(User);
await User.sync({ alter: isDev });
await TwoFa.sync({ alter: isDev });

Below is a test script for creating User and TwoFa

const user = awaitUser.create({
  login: "someLogin",
  email: "[email protected]",
  password: await argon2.hash("sfdsfs"),
});
const twoFaCode = await TwoFa.create(
  {
    ua: "dsfjdskfsd",
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    User: user // тут ругается тайпскрипт
  },
  {
    include: [User],
  },
);

В итоге получаю ошибку

  ValidationErrorItem {
      message: 'id must be unique',
      type: 'unique violation',
      path: 'id',
      value: '14218bdb-5fef-4777-bdfd-094551d09ec5',
      origin: 'DB',
      instance: [User],
      validatorKey: 'not_unique',
      validatorName: null,
      validatorArgs: []
    }

Actually I have 2 questions now:

  1. What did I do wrong in associations?
  2. How to create the correct type to create TwoFa so that there is no typescript error and the key is not User but user

Thanks!

UPD if i add in associations foreignKey: "userId", and when creating TwoFa userId: user.id, then everything will work. Now the question is, why didn’t it work with include?

CodePudding user response:

You're trying to create a user associated with a new TwoFa instance that has the same primary key value.
If you indicate include in create that means you want to create a user along with a TwoFa record and that's not what you want to get.
If you just want to create a TwoFa record and associate it with an existing user then just indicate UserId without include option:

const twoFaCode = await TwoFa.create(
  {
    ua: "dsfjdskfsd",
    UserId: user.id
  }
);

By default you will have a foreign key field name as ModelName Id (UserId) if you don't indicate foreginKey option explicitly in associations

  • Related