mirror of
https://github.com/ent/ent.git
synced 2026-04-28 21:50:56 +03:00
doc/tutorial: update entgql + gqlgen integration (#2915)
This commit is contained in:
@@ -39,7 +39,7 @@ Cursor Connections interface, read the following paragraphs that were taken from
|
||||
|
||||
The code for this tutorial is available under [github.com/a8m/ent-graphql-example](https://github.com/a8m/ent-graphql-example),
|
||||
and tagged (using Git) in each step. If you want to skip the basic setup and start with the initial version of the GraphQL
|
||||
server, you can clone the repository and checkout `v0.1.0` as follows:
|
||||
server, you can clone the repository as follows:
|
||||
|
||||
```console
|
||||
git clone git@github.com:a8m/ent-graphql-example.git
|
||||
@@ -50,9 +50,8 @@ go run ./cmd/todo/
|
||||
|
||||
## Add Annotations To Schema
|
||||
|
||||
Ordering can be defined on any comparable field of ent by annotating it with `entgql.Annotation`.
|
||||
Note that the given `OrderField` name must match its enum value in GraphQL schema (see
|
||||
[next section](#define-ordering-types-in-graphql-schema) below).
|
||||
Ordering can be defined on any comparable field of Ent by annotating it with `entgql.Annotation`.
|
||||
Note that the given `OrderField` name must be uppercase and match its enum value in the GraphQL schema.
|
||||
|
||||
```go title="ent/schema/todo.go"
|
||||
func (Todo) Fields() []ent.Field {
|
||||
@@ -86,82 +85,25 @@ func (Todo) Fields() []ent.Field {
|
||||
}
|
||||
```
|
||||
|
||||
## Define Types In GraphQL Schema
|
||||
|
||||
Next, we need to add the ordering types along with the [Relay Connection Types](https://relay.dev/graphql/connections.htm#sec-Connection-Types)
|
||||
to the GraphQL schema:
|
||||
|
||||
```graphql title="todo.graphql"
|
||||
# Define a Relay Cursor type:
|
||||
# https://relay.dev/graphql/connections.htm#sec-Cursor
|
||||
scalar Cursor
|
||||
|
||||
type PageInfo {
|
||||
hasNextPage: Boolean!
|
||||
hasPreviousPage: Boolean!
|
||||
startCursor: Cursor
|
||||
endCursor: Cursor
|
||||
}
|
||||
|
||||
type TodoConnection {
|
||||
totalCount: Int!
|
||||
pageInfo: PageInfo!
|
||||
edges: [TodoEdge]
|
||||
}
|
||||
|
||||
type TodoEdge {
|
||||
node: Todo
|
||||
cursor: Cursor!
|
||||
}
|
||||
|
||||
# These enums are matched the entgql annotations in the ent/schema.
|
||||
enum TodoOrderField {
|
||||
CREATED_AT
|
||||
PRIORITY
|
||||
STATUS
|
||||
TEXT
|
||||
}
|
||||
|
||||
enum OrderDirection {
|
||||
ASC
|
||||
DESC
|
||||
}
|
||||
|
||||
input TodoOrder {
|
||||
direction: OrderDirection!
|
||||
field: TodoOrderField
|
||||
}
|
||||
```
|
||||
|
||||
Note that the naming must take the form of `<T>OrderField` / `<T>Order` for `autobind`ing to the generated ent types.
|
||||
Alternatively [@goModel](https://gqlgen.com/config/#inline-config-with-directives) directive can be used for manual type binding.
|
||||
|
||||
## Add Pagination Support For Query
|
||||
|
||||
```graphql
|
||||
type Query {
|
||||
todos(
|
||||
after: Cursor
|
||||
first: Int
|
||||
before: Cursor
|
||||
last: Int
|
||||
orderBy: TodoOrder
|
||||
): TodoConnection!
|
||||
1\. The next step for enabling pagination is to tell Ent that the `Todo` type is a Relay Connection.
|
||||
|
||||
```go title="ent/schema/todo.go"
|
||||
func (Todo) Annotations() []schema.Annotation {
|
||||
return []schema.Annotation{
|
||||
//highlight-next-line
|
||||
entgql.RelayConnection(),
|
||||
entgql.QueryField(),
|
||||
entgql.Mutations(entgql.MutationCreate()),
|
||||
}
|
||||
}
|
||||
```
|
||||
That's all for the GraphQL schema changes, let's run `gqlgen` code generation.
|
||||
|
||||
## Update The GraphQL Resolver
|
||||
2\. Then, run `go generate .` and you'll notice that `ent.resolvers.go` was changed. Head over to the `Todos` resolver
|
||||
and update it to pass pagination arguments to `.Paginate()`:
|
||||
|
||||
After changing our Ent and GraphQL schemas, we're ready to run the codegen and use the `Paginate` API:
|
||||
|
||||
```console
|
||||
go generate ./...
|
||||
```
|
||||
|
||||
Head over to the `Todos` resolver and update it to pass `orderBy` argument to `.Paginate()` call:
|
||||
|
||||
```go title="todo.resolvers.go"
|
||||
```go title="ent.resolvers.go" {2-5}
|
||||
func (r *queryResolver) Todos(ctx context.Context, after *ent.Cursor, first *int, before *ent.Cursor, last *int, orderBy *ent.TodoOrder) (*ent.TodoConnection, error) {
|
||||
return r.client.Todo.Query().
|
||||
Paginate(ctx, after, first, before, last,
|
||||
@@ -210,7 +152,7 @@ query {
|
||||
# Output: { "data": { "todos": { "edges": [ { "node": { "id": "16", "text": "Create GraphQL Example" }, "cursor": "gqFpEKF2tkNyZWF0ZSBHcmFwaFFMIEV4YW1wbGU" }, { "node": { "id": "15", "text": "Create GraphQL Example" }, "cursor": "gqFpD6F2tkNyZWF0ZSBHcmFwaFFMIEV4YW1wbGU" }, { "node": { "id": "14", "text": "Create GraphQL Example" }, "cursor": "gqFpDqF2tkNyZWF0ZSBHcmFwaFFMIEV4YW1wbGU" } ] } } }
|
||||
```
|
||||
|
||||
We can also use the cursor we got in the query above to get all items after that cursor:
|
||||
We can also use the cursor we got in the query above to get all items that come after it.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
@@ -230,5 +172,5 @@ query {
|
||||
|
||||
---
|
||||
|
||||
Great! With a few simple changes, our application now supports pagination! Please continue to the next section where we explain how to implement GraphQL field collections and learn how Ent solves
|
||||
the *"N+1 problem"* in GraphQL resolvers.
|
||||
Great! With a few simple changes, our application now supports pagination. Please continue to the next section where we
|
||||
explain how to implement GraphQL field collections and learn how Ent solves the *"N+1 problem"* in GraphQL resolvers.
|
||||
|
||||
Reference in New Issue
Block a user