Let's imagine a scenario where you are displaying a list of posts. You fetch the posts:
And start looping through them:
When you visit the page, though, you notice it takes a while to load. You take a look at your SQL console and you've executed 26 queries for this one page! What?!?
Turns out that each time you loop through a post to display its author's username you are executing a SQL query to retreive that author. With 25 posts this becomes 25 SQL queries plus one initial query to get the posts. This is where the N+1 problem gets its name.
So what is the solution? Eager Loading.
Eager Loading means to load all the needed users for the posts in one query rather than separate queries and then stitch the relationships together. With Quick you can do this with one method call.
You can eager load a relationship with the with
method call.
with
takes one parameter, the name of the relationship to load. Note that this is the name of the function, not the entity name. For example:
To eager load the User in the snippet above you would call pass author
to the with
method.
For this operation, only two queries will be executed:
Quick will then stitch these relationships together so when you call post.getAuthor()
it will use the fetched relationship value instead of going to the database.
You can eager load nested relationships using dot notation. Each segment must be a valid relationship name.
You can eager load multiple relationships by passing an array of relation names to with
or by calling with
multiple times.
In most cases when you want to constrain an eager loaded relationship, the better approach is to create a new relationship.
You can eager load either option.
Occassionally that decision needs to be dynamic. For example, maybe you only want to eager load the posts created within a timeframe defined by a user. To do this, pass a struct instead of a string to the with
function. The key should be the name of the relationship and the value should be a function. This function will accept the related entity as its only argument. Here is an example:
If you need to load nested relationships with constraints you can call with
in your constraint callback to continue eager loading relationships.
Finally, you can postpone eager loading until needed by using the load
method on QuickCollection
. load
has the same function signature as with
. QuickCollection
is the object returned for all Quick queries that return more than one record. Read more about it in Collections.