I'm setting up a NestJS GraphQL API that utilizes TypeORM, and am having trouble implementing relationships between entities.
Specifically, the TypeORM relationships are working great, and the entities are linking correctly in the database. However, the problem comes in when I try to query the API to get the results.
Right now I have 2 entities, each with their own resolver: Users and Photos. Each User can have multiple Photos, while each Photo is only connected to one User (Many-to-One).
Photo Entity, with a relationship to the User Entity
@ManyToOne(type => User, user => user.photos, {
onDelete: 'CASCADE',
})
@JoinColumn()
user: User;
User Entity, completing connection to the Photo Entity
@OneToMany(type => Photo, photo => photo.user, {
eager: true,
})
photos: Photo[];
User resolver
@ResolveProperty('photos')
async photos(@Parent() user): Promise<Photo[]> {
return await this.service.readPhotos(user.id);
}
User service
async readPhotos(userId): Promise<Photo[]> {
return await this.photoRepository.find({
where: {
user: userId
}
});
}
* Note that the photoRepository is able to be filtered by the 'user' field. *
Photo resolver
@ResolveProperty('user')
async user(@Parent() photo): Promise<User> {
console.log(photo);
return await this.service.readUser(photo.user);
}
This Photo resolver seems to contain the problem; the photo object being output by the console indicates that while the @Parent photo object has all of its static fields available (like the ID, datePublished, URL), for some reason the actual 'user' field is not accessible here. So the 'photo.user' variable is null. * Note that this seems to indicated that the photoRepository is UNABLE to be filtered by/access the 'user' field. *
Photo service
async readUser(userId): Promise<User> {
return await this.userRepository.findOne({
where: {
user: userId
}
});
}
This returns null since the userId is blank, due to the previous Photo resolver not being able to access the 'user' field.
Why can't the Photo resolver access the @Parent photo 'user' field? The User service seems to be able to filter by the 'user' field just fine, yet I can't seem to be able to access the Photo 'user' field directly.
Thank you for any help on this! I've been stumped on this for the last two days...
So you'd like to access the user huh? photo.user
? In FindOptions
there's a key called 'relations' this will fetch and apply that for you. So in your example
async readPhotos(userId): Promise<Photo[]> {
return await this.photoRepository.find({
where: {
user: userId
},
relations: ['user'],
});
}
This should now be photo.user
. Another way would be the reverse
async readUser(userId): Promise<User> {
return await this.userRepository.findOne({
where: {
user: userId
},
relations: ['photos'],
});
}
This should now return user.photos
as an array of Photo
s
You can find more examples of FindOptions
usages here http://typeorm.io/#/find-options
Hope this helps!
I was struggling with a similar problem and although @bashleigh's solution works if you want the entire entity returned I only needed the id. So if that's your case you can pass the loadRelationIds
option, and set it to true
.
return await this.photoRepository.find({
where: {
id: photoId
},
loadRelationIds: true
});
This will return user as just the id (string or int).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With