ent

ent

  • Docs
  • GoDoc
  • Github
  • Blog

›Code Generation

Getting Started

  • Quick Introduction

Schema

  • Introduction
  • Fields
  • Edges
  • Indexes
  • Mixin
  • Annotations

Code Generation

  • Introduction
  • CRUD API
  • Graph Traversal
  • Eager Loading
  • Hooks
  • Privacy
  • Transactions
  • Predicates
  • Aggregation
  • Paging And Ordering

Migration

  • Database Migration
  • Supported Dialects

Misc

  • External Templates
  • GraphQL Integration
  • sql.DB Integration
  • Testing
  • FAQ
  • Feature Flags

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

Query all users with their pets:

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:

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.

← Graph TraversalHooks →
  • Overview
  • API
  • Implementation
Docs
Getting StartedSchema GuideCode GenerationSchema Migration
Legal
PrivacyTerms
Credit
The Go gopher was designed by Renee French. The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details.

Design by Moriah Rich, illustration by Ariel Mashraki.
Facebook Open Source
Copyright 2021 Facebook Inc.