---
id: eager-load
title: Eager Loading
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## Overview

`ent` supports querying entities with their associations (through their edges). The associated entities
are populated to the `Edges` field in the returned object.

Let's give an example of what the API looks like for the following schema:

![er-group-users](https://entgo.io/images/assets/er_user_pets_groups.png)



**Query all users with their pets:**
```go
users, err := client.User.
	Query().
	WithPets().
	All(ctx)
if err != nil {
	return err
}
// The returned users look as follows:
//
//	[
//		User {
//			ID:   1,
//			Name: "a8m",
//			Edges: {
//				Pets: [Pet(...), ...]
//				...
//			}
//		},
//		...
//	]
//
for _, u := range users {
	for _, p := range u.Edges.Pets {
		fmt.Printf("User(%v) -> Pet(%v)\n", u.ID, p.ID)
		// Output:
		// User(...) -> Pet(...)
	}
} 
```

Eager loading allows to query more than one association (including nested), and also
filter, sort or limit their result. For example:

```go
admins, err := client.User.
	Query().
	Where(user.Admin(true)).
	// Populate the `pets` that associated with the `admins`.
	WithPets().
	// Populate the first 5 `groups` that associated with the `admins`.
	WithGroups(func(q *ent.GroupQuery) {
		q.Limit(5) 				// Limit to 5.
		q.WithUsers()           // Populate the `users` of each `groups`.
	}).
	All(ctx)
if err != nil {
	return err
}

// The returned users look as follows:
//
//	[
//		User {
//			ID:   1,
//			Name: "admin1",
//			Edges: {
//				Pets:   [Pet(...), ...]
//				Groups: [
//					Group {
//						ID:   7,
//						Name: "GitHub",
//						Edges: {
//							Users: [User(...), ...]
//							...
//						}
//					}
//				]
//			}
//		},
//		...
//	]
//
for _, admin := range admins {
	for _, p := range admin.Edges.Pets {
		fmt.Printf("Admin(%v) -> Pet(%v)\n", u.ID, p.ID)
		// Output:
		// Admin(...) -> Pet(...)
	}
	for _, g := range admin.Edges.Groups {
		for _, u := range g.Edges.Users {
			fmt.Printf("Admin(%v) -> Group(%v) -> User(%v)\n", u.ID, g.ID, u.ID)
			// Output:
			// Admin(...) -> Group(...) -> User(...)
		}
	}
} 
```

## API

Each query-builder has a list of methods in the form of `With<E>(...func(<N>Query))` for each of its edges.
`<E>` stands for the edge name (like, `WithGroups`) and `<N>` for the edge type (like, `GroupQuery`).
 
Note that only SQL dialects support this feature.

## Named Edges

In some cases there is a need for preloading edges with custom names. For example, a GraphQL query that has two aliases
referencing the same edge with different arguments. For this situation, Ent provides another API named `WithNamed<E>`
that can be enabled using the [`namedges`](features.md#named-edges) feature-flag and seamlessly integrated with
[EntGQL Fields Collection](tutorial-todo-gql-field-collection.md).

<Tabs
defaultValue="ent"
values={[
{label: 'Ent', value: 'ent'},
{label: 'GraphQL', value: 'graphql'},
]}>
<TabItem value="ent">

See the GraphQL tab to learn more about the motivation behind this API.

```go
posts, err := client.Post.Query().
    WithNamedComments("published", func(q *ent.CommentQuery) {
        q.Where(comment.StatusEQ(comment.StatusPublished))
    })
    WithNamedComments("draft", func(q *ent.CommentQuery) {
        q.Where(comment.StatusEQ(comment.StatusDraft))
    }).
    Paginate(...)

// Get the preloaded edges by their name:
for _, p := range posts {
    published, err := p.Edges.NamedComments("published")
    if err != nil {
        return err
    }
    draft, err := p.Edges.NamedComments("draft")
    if err != nil {
        return err
    }
}
```

</TabItem>
<TabItem value="graphql">

An example of a GraphQL query that has two aliases referencing the same edge with different arguments.

```graphql
query {
  posts {
    id
    title
    published: comments(where: { status: PUBLISHED }) {
      edges {
        node {
          text
        }
      }
    }
    draft: comments(where: { status: DRAFT }) {
      edges {
        node {
          text
        }
      }
    }
  }
}
```

</TabItem>
</Tabs>

## Implementation

Since an Ent query can eager-load more than one edge, it is not possible to load all associations in a single
`JOIN` operation. Therefore, Ent executes additional query to load each association. This expected to be optimized
in future versions.
