File: eager-load.md

package info (click to toggle)
golang-github-facebook-ent 0.5.4-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 14,284 kB
  • sloc: javascript: 349; makefile: 8
file content (120 lines) | stat: -rw-r--r-- 2,707 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
---
id: eager-load
title: Eager Loading
---

## 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 hows does the API look like for the following schema:

![er-group-users](https://entgo.io/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().Limit(5)	// 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.

## Implementation

Since a query-builder can load more than one association, it's not possible to load them using one `JOIN` operation.
Therefore, `ent` executes additional queries for loading associations. One query for `M2O/O2M` and `O2O` edges, and
2 queries for loading `M2M` edges.

Note that, we expect to improve this in the next versions of `ent`.