How to eager-load relations¶
Configure a batch query¶
A lazy query accepts one parent identifier. Eager loading requires a separate query that accepts many parent identifiers.
-- name: ListPostsByUserIDs :many
SELECT id, user_id, title, body, published, created_at, updated_at
FROM posts
WHERE user_id = ANY(sqlc.arg(user_ids)::UUID[])
ORDER BY user_id, created_at DESC;
Configure the relation¶
relations:
Posts:
lazy_query: ListPostsByUser
eager_query: ListPostsByUserIDs
eager_group_field: user_id
Use eager loading¶
The execution plan is:
- execute the configured users query;
- collect user identifiers;
- execute
ListPostsByUserIDsonce; - group rows by parent key;
- hydrate posts;
- populate every user's canonical
Postscache, including loaded empty slices; - populate configured inverse
Authorcaches with the existing user instance.
Inspect loaded data without SQL¶
for _, user := range users {
posts, loaded := user.Posts().Cached()
if !loaded {
return errors.New("posts were not eager loaded")
}
_ = posts
}
Configure nested eager loading¶
users, err := models.Users.
Query().
WithPosts(func(posts UserPostsEagerLoad) UserPostsEagerLoad {
return posts.WithTags()
}).
Get(ctx)
Nested eager loading is represented by an execution plan, not by public packages such as models/user/posts/tags.
Prevent accidental lazy loading¶
In development:
An uncached Get(ctx) then returns ErrLazyLoadingPrevented. Eager-loaded or already cached relations remain readable.