type-graphql-dataloader
type-graphql-dataloader copied to clipboard
Using TypeormLoader with Lazy fields causes N+1 issue
I am trying to find a way to get entity relations in other internal functions, no just through a resolver.
For example:
- Two Entities (users and companies) are joined by a third entity (user_company_link)
- When resolving User -> User_Company_Link -> Company through a gql resolver, everything works exactly as expected. Dataloader is triggered and the result is only 3 queries against the DB
- When trying to resolve a single User for a specific UCL through an internal request (example below), the User is undefined.
- Turning the User on a UCL into a Promise<User> works for my internal requests as long as I await the UCL.User, but now the resolver has the N+1 problem again as it looks like it is skipping the dataloader
Examples:
//User.entity.ts
export class User {
@Field()
name: string
@Field(() => [UserCompanyLink])
@OneToMany(() => UserCompanyLink, UCL=>UCL.user)
@TypeormLoader()
companyProfiles: UserCompanyLink[]
}
//UserCompanyLink.entity.ts
export class UserCompanyLink {
@Field()
company_title: string
@Field()
company_email: string
@Field(() => User)
@ManyToOne(() => User, U => U.companyProfiles)
@TypeormLoader()
user: User
}
//EmailService.ts
export class EmailService {
//...
async sendEmail(UCL: UserCompanyLink){
const user = UCL.user // <- this is undefined as typeorm hasn't loaded anything
//alternative if UCL.user is Promise<User>
const user = await UCL.user // <- this works as intended here, but now gql resolvers don't use the dataloader
// Use the user.name in the email body, but use the company_email from UCL
}
}
Any advice would be hugely helpful. Thanks!
I dove deeper into the src code and see all the decorators use UseMiddleware from 'typegraphql' so they will only fire on resolvers.
You look understand it correctly. If you directly accessed to a lazy property, it works as it is.
You look understand it correctly. If you directly accessed to a lazy property, it works as it is.
Yes, but turning on Lazy properties causes either N+1 problem, or a very strange infinite loop issue where promises keep trying to resolver themselves and spawn new promises until the whole system crashes.