2 years ago
#17396
mcclosa
GraphQL DataLoader with multiple one to many relations
I'm struggling with a good title for this issue, so apologies. For that.
What I'm trying to achieve;
I have 3 Entities
in use for this dataloader
User
Club
Player
- Each
User
can create aClub
User
has aOneToMany
Relationship withClub
- When a
User
creates aClub
theUser
id
field is set as the value of thecreatorId
field inClub
- The
User
that is the creator of eachClub
can create aPlayer
to assign to theClub
Club
has aOneToMany
Relationship withPlayer
- When a
User
creates aPlayer
at a club theClub
id
field is set as the value of theuserId
field inPlayer
- A
User
who is a creator of aClub
can link aPlayer
to aUser
, theid
field is set as the value of theuserId
field inPlayer
So essentially a single User
can be both a creator of a Club
and a Player
of a Club
, so can be linked to a Club
by either being a creator of a player of the club.
The issue
I want a FieldResolver
field called allClubs
to return all Club
s in which the User
is either the creator or the player of a club.
This is what I currently have
@FieldResolver(() => [Club])
@Loader<number, Club[]>(
async (
userIds,
{
context: {
req: {
session: { userId },
},
},
}: { context: MyContext },
) => {
// get all clubs where user is either creator or a player
const clubs = await getConnection()
.getRepository(Club)
.createQueryBuilder('c')
.distinct()
.leftJoinAndMapMany('c.players', Player, 'p', 'c."id" = p."clubId"')
.where('c."creatorId" In (:...userIds)', { userIds })
.orWhere('p."userId" = :userId', { userId })
.getMany();
// group all clubs by creatorId
const clubsById = groupBy(clubs, 'creatorId');
return userIds.map((id) => clubsById[id] ?? []);
},
)
allClubs(@Root() root: User): (dataloader: DataLoader<number, Club[]>) => Promise<Club[]> {
return (dataloader: DataLoader<number, Club[]>) => dataloader.load(root.id);
}
So, I need the field to return an array of Club
I currently have the key
of the DataLoader as the User
id
Inside the Loader
I have a query that returns all of the clubs where the user is either the creator or the player of the club. With the following structure returned
Club {
id: 5,
name: 'Club Name',
creatorId: 10,
players: [
Player {
id: 2,
name: 'Player name',
clubId: 5,
},
Player {
id: 7,
name: 'Player name 2',
clubId: 5,
}
]
}
I'm not sure how to group it correctly so that when I loop over all of the provided user ids from the key
that I can retrieve where the user is a player.
Currently, it's only where the user is the creator
Let's say for the above example the User
id
is 7
, they are not the creator of the Club
, but they are a Player
, how would I ensure that, that Club
gets returned in the Loader
and not just those Club
s where they are creator?
Any ideas how I can maybe restructure the query in some way to achieve this, or any other methods to achieve the same would be very much appreciated.
javascript
graphql
typeorm
dataloader
typegraphql
0 Answers
Your Answer