Designing Your Schema
Creating an Empty Schema
Schema files are text files, usually named schema.graphql
. You can create this file and submit it to AWS AppSync by using the CLI or navigating
to the console and adding the following under the Schema page:
schema { }
Every schema has this root for processing. This fails to process until you add a root query type.
Adding a Root Query Type
For this example, we create a Todo
application. A GraphQL schema must have a root query type, so we add a root type
named Query
with a single getTodos
field that returns a list containing Todo
objects. Add the following to your schema.graphql
file:
schema { query:Query } type Query { getTodos: [Todo] }
Notice that we haven’t yet defined the Todo
object type. Let’s do that now.
Defining a Todo Type
Now, create a type that contains the data for a Todo
object:
schema { query:Query } type Query { getTodos: [Todo] } type Todo { id: ID! name: String description: String priority: Int }
Notice that the Todo
object typeID
scalar type is a unique identifier that can be either String
or Int
. You can control these in your resolver mapping templates for automatic assignment,
which is covered later.
There are similarities between the Query
and Todo
types. In GraphQL, the root types (that is, Query
, Mutation
, and Subscription
) are similar to the ones you define, but they’re different in that you expose them
from your schema as the entry point for your API. For more information, see The Query and Mutation types
Adding a Mutation Type
Now that you have an object type and can query the data, if you want to add, update,
or delete data via the API you need to add a mutation type to your schema. For the
Todo
example, add this as a field named addTodo
on a mutation type:
schema { query:Query mutation: Mutation } type Query { getTodos: [Todo] } type Mutation { addTodo(id: ID!, name: String, description: String, priority: Int): Todo } type Todo { id: ID! name: String description: String priority: Int }
Note that the mutation is also added to this schema type because it is a root type.
Modifying the Todo Example with a Status
At this point, your GraphQL API is functioning structurally for reading and writing
Todo objects–it just doesn’t have a data source, which is described in the next section.
You can modify this API with more advanced functionality, such as adding a status
to your Todo, which comes from a set of values defined as an ENUM
:
schema { query:Query mutation: Mutation } type Query { getTodos: [Todo] } type Mutation { addTodo(id: ID!, name: String, description: String, priority: Int, status: TodoStatus): Todo } type Todo { id: ID! name: String description: String priority: Int status: TodoStatus } enum TodoStatus { done pending }
Choose Save Schema.
An ENUM
is like a string, but it can take one of a set of values. In the previous example,
you added this type, modified the Todo type, and added the Todo field to contain this
functionality.
Note: You can skip directly to Attaching a Data Source and begin connecting your schema to a data source now, or keep reading to modify your schema with paginations and relational structure.
Subscriptions
Subscriptions in AWS AppSync are invoked as a response to a mutation. You configure
this with a Subscription
type and @aws_subscribe()
directive in the schema to denote which mutations invoke one or more subscriptions.
For more information about configuring subscriptions, see Real-Time Data.
Further Reading
For more information, see the GraphQL type system
Advanced - Relations and Pagination
Suppose you had a million todos
. You wouldn’t want to fetch all of these every time, instead you would want to paginate
through them. Make the following changes to your schema:
-
To the
getTodos
field, add two input arguments:limit
andnextToken
. -
Add a new
TodoConnection
type that hastodos
andnextToken
fields. -
Change
getTodos
so that it returnsTodoConnection
(not a list of Todos).
schema { query:Query mutation: Mutation } type Query { getTodos(limit: Int, nextToken: String): TodoConnection } type Mutation { addTodo(id: ID!, name: String, description: String, priority: Int, status: TodoStatus): Todo } type Todo { id: ID! name: String description: String priority: Int status: TodoStatus } type TodoConnection { todos: [Todo] nextToken: String } enum TodoStatus { done pending }
The TodoConnection
type allows you to return a list of todos
and a nextToken
for getting the next batch of todos
. Note that it is a single TodoConnection
and not a list of connections. Inside the connection is a list of todo items ([Todo]
) which gets returned with a pagination token. In AWS AppSync, this is connected to
Amazon DynamoDB with a mapping template and automatically generated as an encrypted
token. This converts the value of the limit
argument to the maxResults
parameter and the nextToken
argument to the exclusiveStartKey
parameter. For examples and the built-in template samples in the AWS AppSync console,
see Resolver Mapping Template Reference.
Next, suppose your todos have comments, and you want to run a query that returns all
the comments for a todo
. This is handled through GraphQL connections
, as you created in the previous schema. Modify your schema to have a Comment
type, add a comments
field to the Todo
type, and add an addComment
field on the Mutation
type as follows:
schema { query: Query mutation: Mutation } type Query { getTodos(limit: Int, nextToken: String): TodoConnection } type Mutation { addTodo(id: ID!, name: String, description: String, priority: Int, status: TodoStatus): Todo addComment(todoid: ID!, content: String): Comment } type Comment { todoid: ID! commentid: String! content: String } type Todo { id: ID! name: String description: String priority: Int status: TodoStatus comments: [Comment] } type TodoConnection { todos: [Todo] nextToken: String } enum TodoStatus { done pending }
Choose Save Schema.
Note that the Comment
type has the todoid
that it’s associated with, commentid
, and content
. This corresponds to a primary key + sort key combination in the Amazon DynamoDB
table you create later.
The application graph on top of your existing data sources in AWS AppSync enables you to return data from two separate data sources in a single GraphQL query. In the example, the assumption is that there is both a Todos table and a Comments table. We’ll show how to do this in Attaching a Data Source and Configuring Resolvers.