Data aggregations

The JSON/GraphQL based query language for select query is designed to be simple yet powerful. There will still be queries that you cannot express with the select query. For example, getting the number of likes for each article. Aggregations (like counting the number of likes or average rating value) are not supported in the select query syntax. This is conscious decision we’ve made to keep the query language small.

To express complex queries like aggregations, window functions, custom joins etc, use SQL, which is designed for this purpose. If you can express your query in SQL, define a view with it, you can use the data APIs on these views.

Let’s see how we can get the likes of an article.

Let us define a view in SQL:

CREATE VIEW article_like_count AS
   SELECT article_id, COUNT(author_id) AS like_count
   FROM article_like
   GROUP BY article_id;

Create the view in the database by running the above sql query as described here.

Views are read only!

Views are like read-only logical tables on the database. So that means that Data API requests to select will work, but you cannot insert/update/delete items from the view.

We’ve seen how we can get article`s likes using the data APIs. However, this additional information of each article can be attached to the article table using an object relationship say, article_like_count.

Relationships are generally defined using foreign key constraints. However, you cannot define foreign key constraints on/to views. So, in these cases, we can define a relationship without using a foreign keys as described here.

Let’s fetch articles ordered by the number of likes.

query fetch_articles_count {
  article (where: {is_published: {_eq: true}}, order_by: ["+article_like_count.like_count"]) {
     id
     title
     article_like_count {
        like_count
     }
  }
}
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",
        {
          "name" : "article_like_count",
          "columns" : ["like_count"]
        }
    ],
    "where": {"is_published": true},
    "order_by" : "+article_like_count.like_count"
  }
}