Using custom DQL with Slash GraphQL - Dgraph Blog

DQL is Dgraph's own query language. It has GraphQL like syntax but is more versatile than GraphQL. Take a tour of DQL and find it out for yourself.

In this post, we will get started using custom DQL queries with GraphQL in Slash GraphQL. We will continue the Todo Starter Application we built in a previous blog and add some more features to it.

Building a TodoList App

In a previous blog post on Build a React app with Slash GraphQL by Michael we built a Todo app that looked like this:

This time, I want to enhance it, by having todos inside a todo list and having a lot of such different lists. That way, I can keep my todos organized. I will keep all my personal todos in a personal list, learning goal todos in a learning list, office todos in an office list, and so on …

We won't be going over building the UI, but we will just build the backend we need for the UI.

So, I will need a TodoList that will store the Todos. This todo list will need three bits of data:

  • a unique identifier,
  • a name for the list, and,
  • a list of todos that belong to the list.

As a GraphQL type, that's this:

type TodoList {
  id: ID!
  name: String!
  todos: [Todo!]
}

Now, I want the first screen in the UI to show me a summary view of all the todo lists.

In the summary screen, I want the todo lists to appear in a sorted order based on the number of incomplete todos they have. I also want the summary screen to show me the number of incomplete and total todos for each TodoList. That will help me bring the list with the most incomplete todos at the top, so whenever I open my application, the first list I see will be the list that needs the most of my attention.

For this, I need a query in my Slash GraphQL backend that can give me the data needed for rendering the summary screen UI. We won't be able to achieve this with the auto-generated queryTodoList query, because the order argument in that query will only be able to order based on the fields directly present in the TodoList type, it can't order based on some field in the todos inside the TodoList.

Similarly, to get the counts of total and incomplete todos for each TodoList, I will have to query unnecessary data and do some client-side processing, if I were to use the auto-generated queryTodoList query. So, what if the backend could give us the results we want? That is exactly where custom DQL queries come into play.

DQL stands for Dgraph Query Language (Dgraph is the database on top of which Slash GraphQL runs). DQL is a more feature-rich query language that supports variables in queries unlike GraphQL and is better suited for such ad-hoc scenarios which are not fulfilled by the auto-generated GraphQL CRUD API provided by the Slash backend. Custom DQL queries can be easily hooked into the Slash GraphQL backend. Let's see how.

First, let's add the following to our GraphQL schema:

type TodoListSummary @remote {
  id: ID!
  name: String!
  incompleteTodos: Int
  totalTodos: Int
}
type Query {
  queryTodoListSummary: [TodoListSummary] @custom(dql:"""
    query {
      var(func: type(TodoList)) {
        incompleteCount as count(TodoList.todos @filter(eq(Todo.completed, false)))
      }
      queryTodoListSummary(func: uid(incompleteCount), orderdesc: val(incompleteCount)) {
        id: uid
        name: TodoList.name
        incompleteTodos: val(incompleteCount)
        totalTodos: count(TodoList.todos)
      }
    }
  """)
}

Now, let's go over what we just did.

First, we added the TodoListSummary type, which represents the data we need to display the summary for each TodoList in our summary screen. We added @remote directive to this type, to make sure the CRUD API isn't generated for it.

Then, we added a query called queryTodoListSummary which returns a list of TodoListSummary. This query has the @custom directive which indicates that it is a custom query. The dql argument in the directive specifies the DQL query which will be run by Dgraph to fetch the results for this GraphQL query.

To understand the details of how to write such DQL queries, you can look at the docs for Custom DQL. But, for now, let's just understand what the DQL query does. This DQL query orders the TodoLists in descending order of incomplete todos they have and maps the result to TodoListSummary type.

This query can now be used to render the summary screen for TodoLists.

Let's play with our backend now. First of all, let me set the GraphQL schema:

Now, let's go to the API Explorer tab and add some TodoLists containing some Todos using this sample mutation:

mutation {
  addTodoList(input: [
    {
      name: "Learning GraphQL"
      todos: [
        {value: "Get a Slash GraphQL account", completed: true},
        {value: "Deploy a GraphQL backend", completed: true},
        {value: "Learn to use custom DQL queries", completed: true},
        {value: "Build a React app", completed: false},
        {value: "Learn more GraphQL", completed: false}
      ]
    }
    {
      name: "Home tasks"
      todos: [
        {value: "Buy groceries", completed: false},
        {value: "Clean rooms", completed: false},
        {value: "Iron clothes", completed: false}
      ]
    }
    {
      name: "Office tasks"
      todos: [
        {value: "Write blog", completed: true},
        {value: "Get blog reviewed", completed: true},
        {value: "Publish the blog", completed: true},
        {value: "Attract customers", completed: true},
      ]
    }
  ]) {
    todoList {
      id
      name
      todos {
        id
        value
        completed
      }
    }
  }
}

It will give us back the results of the mutation:

Now, let's use our custom query to fetch the summary screen results. So, I am going to run the following query on the Slash GraphQL backend:

query {
  queryTodoListSummary {
    id
    name
    incompleteTodos
    totalTodos
  }
}

Here is what we get back:

See, how easy it is to run custom queries in Slash GraphQL. We got the data that we need to render the summary screen in the order we wanted it to appear.

Summary

We just learned how to use custom DQL queries in Slash GraphQL. You can learn more about DQL from the DQL docs, play with it in the tour, and learn how to use it in your GraphQL API from the Custom DQL in GraphQL docs.

When the auto-generated GraphQL CRUD API doesn't suit your needs, DQL will always be there for the rescue!

ReferencesTop image: Dust and the Helix Nebula

This is a companion discussion topic for the original entry at https://dgraph.io/blog/post/custom-dql-slash-graphql/