Data API Reference: Query Templates

Query templates are used to template queries and to define your own REST interface. Let’s jump into some examples.

Let’s say we would like to query the article table to fetch id and title of all published articles written by an author. We can issue a select query as follows:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "select",
    "args" : {
        "table" : "article",
        "columns": ["id", "title"],
        "where": {
            "is_published": true,
            "author_id" : 1
        }
    }
}

Now, if we find ourselves using this query quite often but with a different value for author_id, it can be convenient to give this query a name and provide author_id as an argument instead of specifying the entire query. This is accomplished with query templates. We can create one using the create_query_template query:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "create_query_template",
    "args" : {
        "name" : "article_minimal",
        "template" : {
            "type" : "select",
            "args" : {
                "table" : "article",
                "columns": ["id", "title"],
                "where": {
                    "author_id": {
                        "$eq" : { "param" : "author_id" }
                    },
                    "is_published" : true
                }
            }
        }
    }
}

In the above request, we’ve templated the author_id in the select query with the parameter author_id instead of a concrete value like 1 and given it the name “article_minimal”. Now to execute this query template:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "execute_query_template",
    "args" : {
        "name" : "article_minimal",
        "args" : {
            "author_id" : 1
        }
    }
}

This query executes the query template article_minimal with author_id set to 1.

As you may have noticed, query templates are extremely useful in fetching highly nested data. The query templates are not limited to select, you can also template insert, update, delete, count and bulk queries.

Query templates also let you define a REST interface for your application. For example, you can also execute the above query template as follows:

GET data.<cluster-name>.hasura-app.io/v1/template/article_minimal?author_id=1 HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

While the above example uses the GET method, you can also use PUT, DELETE, POST as appropriate to the query that you have templated.

Here is another example where a delete query is templated:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "create_query_template",
    "args" : {
        "name" : "delete_article_tag",
        "template" : {
            "type" : "delete",
            "args" : {
                "table" : "article_tag",
                "where": {
                    "article_id": {
                        "$eq" : { "param" : "article_id" }
                    },
                    "tag": {
                        "name" : {
                            "$eq" : { "param" : "tag_name" }
                        }
                    },
                    "article" : {
                        "is_published" : false
                    }
                }
            }
        }
    }
}

We would like to allow authors to delete a tag on articles if they are not yet published. The above query template can be used for this purpose. It has two parameters article_id and tag_name. To execute the query template:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "execute_query_template",
    "args" : {
        "name" : "article_minimal",
        "args" : {
            "article_id" : 1,
            "tag_name" : "opinion"
        }
    }
}

or

DELETE data.<cluster-name>.hasura-app.io/v1/template/delete_article_tag?article_id=1&tag_name=opinion HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

Permissions on query templates

When executing a query template, the template is essentially converted into a query. So, the permissions on the query automatically apply. For example, if there are no permissions for anonymous role to select from a table, then, there are no permissions for anonymous role to execute a templated select query on the table.

create_query_template

create_query_template is used to template a query and attach a name to it.

Here is an example for a select query which uses the default values in the template parameters.

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "create_query_template",
    "args" : {
        "name" : "article_homepage",
        "template": {
          "type": "select",
          "args": {
            "table" : "article",
            "columns": ["id", "title"],
            "where": {
                "is_published": {
                    "$eq" : { "param" : "is_published" }
                },
                "article_like_count" : {
                    "like_count" : {
                        "$gt" : { "param" : "like_count_min" }
                    }
                }
            },
            "limit" : {
                "param" : "limit",
                "default" : 10
            },
            "offset" : {
                "param" : "offset",
                "default" : 0
            }
          }
       }
    }
}

The limit and offset parameters each define a default value. These are used when these parameters are not provided during the execution.

The following section describes the syntax of create_query_template and the parts of each query that can be templated.

Syntax

Key Required Schema Description
name true String Name of the query template
template true TemplatedQuery A query which is templated
comment false Text A comment, probably describing the query template

TemplatedQuery

A Query with TemplateParam for concrete values in a query. The queries that can be templated are select, insert, update, delete, count and bulk. The templatable parts of these queries are as follows:

Query type Templatable parts
select values in the where clause, limit and offset
insert only the objects key
update values in the where clause, values of $set, $inc, $mul
delete values in the where clause
count values in the where clause
bulk templatable parts of the included queries

TemplateParam

Key Required Schema Description
param true Text A parameter name
default false Value A default value which is used when this parameter is not provided during execution

Let’s look at examples for other query types mentioned above.

Here’s an example for an insert query.

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "create_query_template",
    "args" : {
        "name" : "insert_article",
        "template" : {
          "type" : "insert",
          "args" : {
              "table" : "article",
              "objects" : {
                 "param" : "article_objects"
              }
          }
       }
    }
}

As mentioned above, only the objects key in a insert query is templatable. This would insert n number of articles into the article table, where n is the length of the article_objects array.

Here’s an example for an update query.

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "create_query_template",
    "args" : {
        "name" : "update_article_author",
        "template" : {
          "type" : "update",
          "args" : {
              "table" : "article",
              "$set" : {
                 "author_id" : {
                   "param" : "author_id"
                 }
               },
               "where" : {
                 "is_published" : {
                   "$eq" : true
                 }
               }
          }
       }
    }
}

In the above example, we are trying to update the author of all articles which are published. Note that $set has the templated param author_id.

execute_query_template

Execute any query template. Let’s execute the query template defined above:

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "execute_query_template",
    "args" : {
        "name" : "article_homepage",
        "args" : {
            "is_published" : true,
            "article_like_count" : 20,
            "limit" : 50
        }
    }
}

This would fetch the first 50 published articles which have at least 20 likes.

You can also execute a query template by making a HTTP request to /v1/template/<template_name>. The HTTP method used defines how the arguments to the template are obtained.

HTTP Method Template arguments
GET url parameters
POST url parameters and json body. The arguments in the body take precedence.
PUT url parameters and json body. The arguments in the body take precedence.
DELETE url parameters

For example, the article_homepage template can be executed by any of the following means. All are equivalent.

GET data.<cluster-name>.hasura-app.io/v1/template/article_homepage?is_published=true&like_count_min=20&limit=50 HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access
POST data.<cluster-name>.hasura-app.io/v1/template/article_homepage?is_published=true&limit=20 HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "article_like_count" : 20,
    "limit" : 50
}
PUT data.<cluster-name>.hasura-app.io/v1/template/article_homepage?is_published=true&limit=20 HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "article_like_count" : 20,
    "limit" : 50
}
DELETE data.<cluster-name>.hasura-app.io/v1/template/article_homepage?is_published=true&like_count_min=20&limit=50 HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

In the above example, in case of POST and PUT, the parameters in the body override the url parameters and hence they are all equivalent.

Note

There is no enforcement from the data microservice on the method used to execute a query template (i.e, you can use the DELETE verb to execute a query template on select). It is left to the developer to use the method appropriate for the template.

Syntax

Key Required Schema Description
name true String Name of the query template
args true Object (TemplateParam : Value) An object with parameter names for keys and template arguments for values

drop_query_template

drop_query_template is used to drop an existing query template.

POST data.<cluster-name>.hasura-app.io/v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type" : "drop_query_template",
    "args" : {
        "name" : "article_minimal"
    }
}

Syntax

Key Required Schema Description
name true String Name of the query template

set_query_template_comment

set_query_template_comment is used to set/update the comment on a query template. Setting the comment to null removes it. For example,

POST /v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type": "set_query_template_comment",
    "args": {
        "name": "article_homepage",
        "comment" : "used for homepage data"
    }
}

Syntax

Key Required Schema Description
name true String The name of the query template
comment false Text comment

List existing query templates

To fetch a list of created query templates, run the following query using psql or adminer:

select * from hdb_catalog.hdb_query_template;

You can also issue the following query to the data microservice.

POST /v1/query HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: <role>  # optional. Pass if only specific user role has access

{
    "type": "select",
    "args": {
        "table" : {
            "schema" : "hdb_catalog",
            "name" : "hdb_query_template"
        },
        "columns": ["template_name", "template_defn", "comment"]
    }
}

Note

Query templates are in beta. However, the API has been stabilised and will not change in future.