Eager Loading
Efficiently load related data in a single query to avoid N+1 problems.
The N+1 Problem
Without eager loading, fetching related data requires multiple queries:
n-plus-one.ts
// Bad: N+1 queries
const users = await db.query(cook`main:users slay:*`); // 1 query
for (const user of users) {
// N additional queries!
user.posts = await db.query(cook`main:posts slay:* sus:user_id=${user.id}`);
}
// Good: Single query with eager loading
const users = await db.query(cook`main:users slay:* fam:posts`); // 1-2 queries totalBasic Eager Loading
basic.ts
// Load single relation
const users = await db.query(
cook`main:users slay:* fam:profile`
);
// Load multiple relations
const users = await db.query(
cook`main:users slay:* fam:profile,posts`
);Nested Eager Loading
nested.ts
// Load nested relations with dot notation
const users = await db.query(
cook`main:users slay:* fam:posts.comments`
);
// Result: users → posts → comments
// Multiple levels deep
const users = await db.query(
cook`main:users slay:* fam:posts.comments.author`
);
// Result: users → posts → comments → authorConstrained Eager Loading
constrained.ts
// Filter related records
const users = await db.query(
cook`main:users slay:* fam:posts(sus:published=true)`
);
// Only loads published posts
// Order related records
const users = await db.query(
cook`main:users slay:* fam:posts(vibe:created_at/desc)`
);
// Posts ordered by date
// Limit related records
const users = await db.query(
cook`main:users slay:* fam:posts(bet:5 vibe:created_at/desc)`
);
// Only latest 5 posts per userSelect Specific Columns
select-columns.ts
// Select only needed columns from relations
const users = await db.query(
cook`main:users slay:id,name fam:posts(slay:id,title)`
);
// { id: 1, name: "John", posts: [{ id: 1, title: "Hello" }] }Loading Strategies
Subquery (Default)
Uses separate queries for each relation. Best for hasMany relations to avoid row multiplication.
Join
Uses SQL JOINs. More efficient for hasOne/belongsTo but can cause row duplication with hasMany.
strategies.ts
// Force join strategy
const users = await db.query(
cook`main:users slay:* fam:profile/join`
);
// Force subquery strategy
const users = await db.query(
cook`main:users slay:* fam:posts/subquery`
);Performance Tip
Only eager load what you need. Loading unnecessary relations wastes database resources and memory. Use constrained loading to limit data.