sequelize-typescript icon indicating copy to clipboard operation
sequelize-typescript copied to clipboard

How do I make a one-to-one relationship optional?

Open MaksiRose opened this issue 2 years ago • 1 comments

Issue

So I have several places where this is true, but one of them is the relationship between the "User" and "Quid" table. Each user can have several quids, and each quid belongs to one user, so that part has no problems. but additionally, one and exactly one of those quids can be the "global last proxied" one. So I have a column on the user table which is called proxy_lastGlobalProxiedQuidId. But this is a One-to-one relationship, which means that each quid is also looking to belong to one of these fields. But that is not true, not every quid is the last global proxied quid of a user. So some quids have that one-to-one relationship, while others just dont have that relationship at all. How exactly do I make this optional on the quids part? I tried just adding allowNull:true but it doesn't exist in the options for the decorator. Here is my code: image image

Versions

  • sequelize: 6.28.0
  • sequelize-typescript: 2.1.5
  • typescript: 4.9.5

MaksiRose avatar Feb 24 '23 11:02 MaksiRose

So, if a User instance have multiple Quid instances and a Quid instance can only belong to one user, you have a 1:N (OneToMany) association.

If only one Quid instance is a GlobalProxiedQuid, you can mark him as one, instead of using it's foreign key.

So, your association would be something like:

(user.ts)

public class User extends Table<...>{
 /** ... */
 @HasMany(() => Quid)
 quids: Quid[];

}

(quid.ts)

public Class Quid extends Table<...>{
 @ForeignKey(() => User)
 @Column({ type: DataType.INTEGER /** ... */ }) //If you're using surrogate keys, then the DataType must be INTEGER
 declare fk_user: number | null;

 @BelongsTo(() => User)
 user: User;

 @Column
 isLasGlobalProxiedQuid: boolean;
}

That way, if some user have a globalProxiedQuid, he will be marked with a quid that has "isLasGlobalProxiedQuid" set to true.

Other two junkier ways to do it is:

Have a different table that only have lastGlobalProxiedQuids, so the User would associate with both Quid and then, you could check if the Quid is listed in LastGlobalProxiedQuids.

(quid.ts)

public Class Quid extends Table<...>{
 @ForeignKey(() => User)
 @Column({ type: DataType.INTEGER /** ... */ }) //If you're using surrogate keys, then the DataType must be INTEGER
 declare fk_user: number | null;

 @BelongsTo(() => User)
 user: User;

 @HasMany(() => LastGlobalProxiedQuid) //Considering that somehow multiple LastGlobalProxiedQuids exists
 quids: Quid[];
}

(lastGlobalProxiedQuid.ts)

public Class LastGlobalProxiedQuid extends Table<...>{
 @ForeignKey(() => Quid)
 @Column({ type: DataType.INTEGER /** ... */ }) //If you're using surrogate keys, then the DataType must be INTEGER
 declare fk_quid: number | null;

 @BelongsTo(() => Quid)
 quid: Quid;

}

And the other method to do it is to have the same thing but with LastGlobalProxiedQuid associated with User, so you could compare both (idk why someone would do it).

lik3as avatar Oct 27 '23 19:10 lik3as