I don't get GraphQL. How do you solve the N+1 issue without preloading?

1.1k Views Asked by At

A neighborhood has many homes. Each home is owned by a person.

Say I have this graphql query:

{
    neighborhoods {
        homes {
            owner {
                name
            }
        }
    }
}

I can preload the owners, and that'll make the data request be a single SQL query. Fine.

But what if I don't request the owner in the graphql query, the data will still be preloaded.

And if I don't preload, the data will either be fetched in every query, or not at all since I'm not loading the belongs_to association in the resolver.

I'm not sure if this is a solved issue, or just a painpoint one must swallow when working with graphql.

Using Absinthe, DataLoader and Elixir by the way.

2

There are 2 best solutions below

0
On

Most GraphQL implementations, including Absinthe, expose some kind of "info" parameter that contains information specific to the field being resolved and the request being executed. You can parse this object to determine which fields were actually requested and build your SQL query appropriately.

See this issue for a more in-depth discussion.

0
On

In order to complement what Daniel Rearden said, you have to use the info.definition to resolve nested includes.

In my application I defined an array of possible values like:

defp relationships do
  [
    {:person, [tasks: [:items]]]}
    ...
   ]
end

then I have a logic that iterates over the info.definition and uses this function to preload the associations.

You will use a DataLoader to lazy load your resources. Usually to fetch third party requests or perform a complex database query.