jeudi 22 avril 2021

Issue with N+1 queries with accessors when using Lighthouse GraphQL and Laravel

I'm having a bit of an issue with the old N+1 problem. I'm running Lighthouse 4.8, Laravel 5.8, and have batched_queries and batchload_relations set to true in my config. I have the hasMany and hasOne set in my schema (anonymised a little):

type Team {
    id: Int!
    Y_resource_id: Int
    X_resource_id: Int
    name: String
    description: String
    start_date: Date
    cost: Float
    Y: Resource @hasOne
    X: Resource @hasOne
    members(
        where: _ @whereConditions
        hasDepartmentMember: _ @whereHasConditions(columns: ["z_id","start_date"])
        orderBy: [OrderByClause!] @orderBy
    ): [TeamMember] @hasMany @is_logged_in
    options: [TeamResourceOption] @hasMany
    optionIds: [Int!]
}

I'm using multiple accessor functions which utilise these relationships, as well as some custom resolvers and local scopes. These seem to be the ones that are causing the N+1 issues, for example when I am loading in a Team, one of the php queries that is having the N+1 issue is this (on the Team model after trying to load a team in and populate information):

public function getHasTeamLeaderAttribute(): bool
{
    return $this->members()->teamLeaders()->count() > 0;
}

this is the members() function:

public function members(): HasMany

{
    return $this->hasMany(TeamMember::class);
}

and the on the TeamMember class:

public function scopeTeamLeaders($query)
{
    return $query->where('team_members.group_role', '=', TeamMember::ROLE_TEAM_LEADER);
}

Clockwork is showing this as 2 N+1 issues (I'm calling it twice):

N+1 queries: App\Models\Teams\Team::App\Models\Teams\TeamMember loaded 4 times.
Team.php:254
N+1 queries: App\Models\Teams\Team::App\Models\Teams\TeamMember loaded 2 times.
Team.php:254

I have tried using loadMissing in the accessor to load in the teamLeaders but this seems to increase the N+1 queries, and I have also tried loading the model with $with the relationships I need, however this makes the entire application slower (I assume because it's now autoloading it in where it's not needed).

This is an inherited project, and I'm not completely au fait with GraphQL so any pointers in the right direction would be great. Thanks!



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire