Page updated Nov 21, 2023

GraphQL query with sorting by date

In this guide you will learn how to implement sorting in a GraphQL API. In our example, you will implement sorting results by date in either an ascending or descending order by implementing an additional data access pattern leveraging a DynamoDB Global Secondary Index using the @index GraphQL Transformer directive.


To get started, let's start with a basic GraphQL schema for a Todo app:

type Todo @model { id: ID! title: String! }
1type Todo @model {
2 id: ID!
3 title: String!

When the API is created with an @model directive, the following queries will automatically be created for you:

type Query { getTodo(id: ID!): Todo listTodos( filter: ModelTodoFilterInput limit: Int nextToken: String ): ModelTodoConnection }
1type Query {
2 getTodo(id: ID!): Todo
3 listTodos(
4 filter: ModelTodoFilterInput
5 limit: Int
6 nextToken: String
7 ): ModelTodoConnection

Next, take a look at the ModelTodoConnection type to get an idea of the data that will be returned when the listTodos query is run:

type ModelTodoConnection { items: [Todo] nextToken: String }
1type ModelTodoConnection {
2 items: [Todo]
3 nextToken: String

By default, the listTodos query will return the items array unordered. Many times you will need these items to be ordered by title, by creation date, or in some other way.

To enable this, you can use the @index directive. This directive will allow you to set a custom sortKey on any field in your API.


In this example, you will enable sorting by the createdAt field. By default, Amplify will populate this createdAt field with a timestamp if none is passed in.

To enable this, update your schema with the following:

type Todo @model { id: ID! title: String! type: String! @index( name: "todosByDate" queryField: "todosByDate" sortKeyFields: ["createdAt"] ) createdAt: String! }
1type Todo @model {
2 id: ID!
3 title: String!
4 type: String!
5 @index(
6 name: "todosByDate"
7 queryField: "todosByDate"
8 sortKeyFields: ["createdAt"]
9 )
10 createdAt: String!

When created a Todo, you must now populate the type field for this to work properly.

Next, create a few todos being sure to populate the type field:

mutation createTodo { createTodo(input: { title: "Todo 1", type: "Todo" }) { id title } }
1mutation createTodo {
2 createTodo(input: { title: "Todo 1", type: "Todo" }) {
3 id
4 title
5 }

Now, you can query for todos by date in an ascending or descending order using the new todosByDate query:

query todosByDate { todosByDate(type: "Todo", sortDirection: ASC) { items { id title createdAt } } } query todosByDateDescending { todosByDate(type: "Todo", sortDirection: DESC) { items { id title createdAt } } }
1query todosByDate {
2 todosByDate(type: "Todo", sortDirection: ASC) {
3 items {
4 id
5 title
6 createdAt
7 }
8 }
11query todosByDateDescending {
12 todosByDate(type: "Todo", sortDirection: DESC) {
13 items {
14 id
15 title
16 createdAt
17 }
18 }

To learn more about the @index directive, check out the documentation here