2018-09-11 14:11:24 +03:00
|
|
|
|
Derived data in queries
|
|
|
|
|
=======================
|
2018-11-15 14:43:03 +03:00
|
|
|
|
|
2018-12-03 15:12:24 +03:00
|
|
|
|
.. contents:: Table of contents
|
|
|
|
|
:backlinks: none
|
2019-09-05 17:53:50 +03:00
|
|
|
|
:depth: 2
|
2018-12-03 15:12:24 +03:00
|
|
|
|
:local:
|
|
|
|
|
|
2018-11-15 14:43:03 +03:00
|
|
|
|
GraphQL’s "select" query language is designed to be simple yet powerful. But there are certain
|
|
|
|
|
queries that you cannot express with a simple GraphQL query. For example, getting data from a custom join.
|
2018-09-11 14:11:24 +03:00
|
|
|
|
|
|
|
|
|
To express complex queries for derived data like aggregations or custom joins etc., use SQL, which is designed for this
|
2018-11-15 14:43:03 +03:00
|
|
|
|
purpose. If you can express your query in SQL, define a view with it and then use the newly created
|
2018-09-11 14:11:24 +03:00
|
|
|
|
type in the GraphQL query.
|
|
|
|
|
|
2018-11-15 14:43:03 +03:00
|
|
|
|
.. note::
|
|
|
|
|
Also see :doc:`aggregation-queries` to fetch aggregation data without creating a view.
|
|
|
|
|
|
2019-04-19 13:48:18 +03:00
|
|
|
|
**For example**, let’s see how to fetch the average article rating for each author in our author/article schema:
|
2018-09-11 14:11:24 +03:00
|
|
|
|
|
2018-12-03 15:12:24 +03:00
|
|
|
|
Step 1: Create a view
|
|
|
|
|
---------------------
|
2018-09-11 14:11:24 +03:00
|
|
|
|
Open the Hasura console and head to the ``Data -> SQL`` tab.
|
|
|
|
|
|
|
|
|
|
A view that averages the rating of articles for each author can be created using the following SQL query:
|
|
|
|
|
|
|
|
|
|
.. code-block:: SQL
|
|
|
|
|
|
|
|
|
|
CREATE VIEW author_average_rating AS
|
2019-04-19 13:48:18 +03:00
|
|
|
|
SELECT author.id, avg(article.rating)
|
|
|
|
|
FROM author, article
|
|
|
|
|
WHERE author.id = article.author_id
|
|
|
|
|
GROUP BY author.id
|
2018-09-11 14:11:24 +03:00
|
|
|
|
|
2018-12-03 15:12:24 +03:00
|
|
|
|
Step 2: Add a relationship
|
|
|
|
|
--------------------------
|
2018-09-11 14:11:24 +03:00
|
|
|
|
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-key as described
|
|
|
|
|
:doc:`here <../schema/relationships/index>`.
|
|
|
|
|
|
|
|
|
|
Create an object relationship, ``avg_rating``, by mapping ``author::id -> author_average_rating::id``.
|
|
|
|
|
|
2018-12-03 15:12:24 +03:00
|
|
|
|
Step 3: Query using the relationship
|
|
|
|
|
------------------------------------
|
2019-09-11 10:17:14 +03:00
|
|
|
|
Now that the relationship between the ``author`` table and the ``author_average_rating`` view has been set
|
2018-09-11 14:11:24 +03:00
|
|
|
|
up, we can query the aggregate data in ``author_average_rating`` as with any regular nested object.
|
|
|
|
|
|
|
|
|
|
Fetch a list of authors along with their average article rating:
|
|
|
|
|
|
|
|
|
|
.. graphiql::
|
|
|
|
|
:view_only:
|
|
|
|
|
:query:
|
|
|
|
|
query {
|
|
|
|
|
author {
|
|
|
|
|
id
|
|
|
|
|
name
|
|
|
|
|
avg_rating {
|
|
|
|
|
avg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
:response:
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"author": [
|
|
|
|
|
{
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "Justin",
|
|
|
|
|
"avg_rating": {
|
|
|
|
|
"avg": 2.5
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 2,
|
|
|
|
|
"name": "Beltran",
|
|
|
|
|
"avg_rating": {
|
|
|
|
|
"avg": 3
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 3,
|
|
|
|
|
"name": "Sidney",
|
|
|
|
|
"avg_rating": {
|
|
|
|
|
"avg": 2.6666666666666665
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"id": 4,
|
|
|
|
|
"name": "Anjela",
|
|
|
|
|
"avg_rating": {
|
|
|
|
|
"avg": 2.5
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-15 14:43:03 +03:00
|
|
|
|
This example can be easily extended to cover any use-case involving a complicated SQL query that you may want to use.
|