because I don't want use cascade to update the join table and I want custom columns, I've created a custom many to many relationship. However when I query the relation it only provides the values in the join table and doesn't pull the relation data.
User
@Entity('user')
export class User {
@PrimaryColumn()
id: string;
@OneToMany(
() => UserArtistFollowing,
(userArtistFollowing) => userArtistFollowing.user
)
following: UserArtistFollowing[];
}
Artist
@Entity('artist')
export class Artist {
@PrimaryGeneratedColumn('uuid')
id: string;
@OneToMany(
() => UserArtistFollowing,
(userArtistFollowing) => userArtistFollowing.artist
)
usersFollowing: UserArtistFollowing[];
}
UserArtistFollowing
@Entity('userArtistFollowing')
export class UserArtistFollowing {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
userId!: string;
@Column()
artistId!: string;
@ManyToOne(
() => User,
(user) => user.following
)
user!: User;
@ManyToOne(
() => Artist,
(artist) => artist.usersFollowing
)
artist!: Artist;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
Query
const user = await getManager()
.getRepository(Models.User)
.findOne({
where: { id: id },
relations: ['following'],
});
So that query only provides the id, userId, artistId, but not the Artist array of objects (which is the data I need).
Thoughts?
After further testing, turns out you can use find -> relations with these kinds of custom many to many relationships. You just have to specify the relation in dotted notation for nested relations.
const user = await getManager()
.getRepository(Models.User)
.findOne({
where: { id },
relations: [
// you have to specify the join table first (following) to retrieve the columns in the join table
'following',
// then you use dotted notation to get the relation from the join table
'following.artist',
// another example of a deeply nested relation
'favourites',
'favourites.song',
'favourites.song.supportingArtists',
'favourites.song.supportingArtists.artist',
],
});
You can also use join with a nested leftJoinAndSelect, but its more tedious.
const user = await getManager()
.getRepository(Models.User)
.findOne({
where: { id },
join: {
alias: 'user',
leftJoinAndSelect: {
following: 'user.following',
artists: 'following.artist',
},
},
});
Here is the updated entities
UserArtistFollowing
@Entity('userArtistFollowing')
export class UserArtistFollowing {
@PrimaryColumn()
userId: string;
@PrimaryColumn()
artistId: string;
@ManyToOne(
() => User,
(user) => user.following
)
user!: User;
@ManyToOne(
() => Artist,
(artist) => artist.usersFollowing
)
artist!: Artist;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
Artist
@Entity('artist')
export class Artist {
@PrimaryGeneratedColumn('uuid')
id: string;
@OneToMany(
() => UserArtistFollowing,
(userArtistFollowing) => userArtistFollowing.artist
)
usersFollowing: UserArtistFollowing[];
}
User
@Entity('user')
export class User {
@PrimaryColumn()
id: string;
@OneToMany(
() => UserArtistFollowing,
(userArtistFollowing) => userArtistFollowing.user
)
following: UserArtistFollowing[];
}