diff --git a/docs/graphql/manual/api-reference/query.rst b/docs/graphql/manual/api-reference/query.rst index b2db33c3af0..bd0481c0c89 100644 --- a/docs/graphql/manual/api-reference/query.rst +++ b/docs/graphql/manual/api-reference/query.rst @@ -241,4 +241,5 @@ PaginationExp .. parsed-literal:: - limit: Integer [offset: Integer] + limit: Integer + [offset: Integer] diff --git a/docs/graphql/manual/deployment/graphql-engine-flags/reference.rst b/docs/graphql/manual/deployment/graphql-engine-flags/reference.rst index 2be77d44cd5..6924f7dd23e 100644 --- a/docs/graphql/manual/deployment/graphql-engine-flags/reference.rst +++ b/docs/graphql/manual/deployment/graphql-engine-flags/reference.rst @@ -5,7 +5,7 @@ Every GraphQL engine command is structured as: .. code-block:: bash - graphql-engine serve + $ graphql-engine serve Server flags ^^^^^^^^^^^^ diff --git a/docs/graphql/manual/guides/deployment/index.rst b/docs/graphql/manual/guides/deployment/index.rst index c07d46a8c07..f1c6d5e32e6 100644 --- a/docs/graphql/manual/guides/deployment/index.rst +++ b/docs/graphql/manual/guides/deployment/index.rst @@ -3,6 +3,7 @@ Guides: Deployment - :doc:`Deploy on Digital Ocean using Docker ` - :doc:`Digital Ocean One-click App ` +- `Blog: Instant GraphQL on AWS RDS `__ .. note:: The above are guides to deploy Hasura GraphQL engine on some specific platforms. diff --git a/docs/graphql/manual/guides/index.rst b/docs/graphql/manual/guides/index.rst index 72e983d4274..48eb8f08134 100644 --- a/docs/graphql/manual/guides/index.rst +++ b/docs/graphql/manual/guides/index.rst @@ -6,6 +6,7 @@ Deployment guides - :doc:`Deploy on Digital Ocean using Docker ` - :doc:`Digital Ocean One-click App ` +- `Blog: Instant GraphQL on AWS RDS `__ .. note:: The above are guides to deploy Hasura GraphQL engine on some specific platforms. diff --git a/docs/graphql/manual/queries/query-filters.rst b/docs/graphql/manual/queries/query-filters.rst index 428a17945a2..52237161cbb 100644 --- a/docs/graphql/manual/queries/query-filters.rst +++ b/docs/graphql/manual/queries/query-filters.rst @@ -1,11 +1,11 @@ Filter query results / search queries ===================================== -You can use the ``where`` argument in your queries to filter the results based on a field’s values (including in a -nested object’s fields). You can even use multiple filters in the same ``where`` clause using the ``_and`` or the +You can use the ``where`` argument in your queries to filter results based on some field’s values (even +nested objects' fields). You can even use multiple filters in the same ``where`` clause using the ``_and`` or the ``_or`` operators. -For example, fetch data for an author whose name is "Sidney": +For example, to fetch data for an author whose name is "Sidney": .. code-block:: graphql :emphasize-lines: 3 @@ -19,24 +19,29 @@ For example, fetch data for an author whose name is "Sidney": } } -You can also use the nested ``articles`` object to filter rows from the ``author`` table. This query fetches a list of -authors who have articles with a rating greater than 4: +You can also use nested objects` fields to filter rows from a table and also filter the nested objects as well. + +For example, to fetch a list of authors who have articles with a rating greater than 4 along with those articles: .. code-block:: graphql - :emphasize-lines: 3 + :emphasize-lines: 2,5 query { - author( - where: {articles: {rating: {_gt: 4}}} - ) { + author (where: {articles: {rating: {_gt: 4}}}) { id name + articles (where: {rating: {_gt: 4}}) { + id + title + rating + } } } -``_eq`` and ``_gt`` are examples of comparison operators that can be used in the ``where`` argument to filter on -equality. Let’s take a look at different operators that can be used to filter results and the field types these -operators are compatible with. +Here ``_eq`` and ``_gt`` are examples of comparison operators that can be used in the ``where`` argument to filter on +equality. + +Let’s take a look at different operators that can be used to filter results and other advanced use cases: Equality operators (_eq and _neq) --------------------------------- @@ -465,7 +470,7 @@ Fetch a list of authors whose names begin with A or C (``similar`` is case-sensi Filter or check for null values ------------------------------- -Checking for null values is pretty straightforward using the ``_is_null`` operator. +Checking for null values can be achieved using the ``_is_null`` operator. Example: Filter null values in a field ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -511,11 +516,77 @@ Fetch a list of articles that have a value in the ``published_on`` field: } } +Filter based on failure of some criteria +---------------------------------------- + +The ``_not`` operator can be used to fetch results for which some condition does not hold true. i.e. to invert the +filter set for a condition + +Example: _not +^^^^^^^^^^^^^ +Fetch all authors who don't have any published articles: + +.. graphiql:: + :view_only: + :query: + { + author( + where: { + _not: { + articles: { is_published: {_eq: true} } + } + }) { + id + name + articles { + title + is_published + } + } + } + :response: + { + "data": { + "author": [ + { + "id": 7, + "name": "Berti", + "articles": [ + { + "title": "ipsum primis in", + "is_published": false + } + ] + }, + { + "id": 9, + "name": "Ninnetta", + "articles": [] + }, + { + "id": 10, + "name": "Lyndsay", + "articles": [ + { + "title": "dui proin leo", + "is_published": false + } + ] + } + ] + } + } + Using multiple filters in the same query ---------------------------------------- You can group multiple parameters in the same ``where`` argument using the ``_and`` or the ``_or`` operators to filter results based on more than one criteria. + +.. note:: + You can use the ``_or`` and ``_and`` operators along with the ``_not`` operator to create arbitrarily complex boolean + expressions involving multiple filtering criteria. + Example: _and ^^^^^^^^^^^^^^ Fetch a list of articles published in a specific time-frame (for example: in year 2017): @@ -620,3 +691,468 @@ Fetch a list of articles rated more than 4 or published after "01/01/2018": ] } } + + +Filter nested objects +--------------------- +The ``where`` argument can be used in nested objects as well to filter the nested objects + +Example: +^^^^^^^^ +Fetch all authors with only their 5 rated articles: + +.. graphiql:: + :view_only: + :query: + { + author { + id + name + articles(where: {rating: {_eq: 5}}) { + title + rating + } + } + } + :response: + { + "data": { + "author": [ + { + "id": 1, + "name": "Justin", + "articles": [] + }, + { + "id": 2, + "name": "Beltran", + "articles": [] + }, + { + "id": 3, + "name": "Sidney", + "articles": [] + }, + { + "id": 4, + "name": "Anjela", + "articles": [] + }, + { + "id": 5, + "name": "Amii", + "articles": [ + { + "title": "montes nascetur ridiculus", + "rating": 5 + } + ] + }, + { + "id": 6, + "name": "Corny", + "articles": [] + }, + { + "id": 7, + "name": "Berti", + "articles": [] + }, + { + "id": 8, + "name": "April", + "articles": [] + }, + { + "id": 9, + "name": "Ninnetta", + "articles": [] + }, + { + "id": 10, + "name": "Lyndsay", + "articles": [] + } + ] + } + } + + +Filter based on nested objects' fields +-------------------------------------- + +You can use the fields of nested objects as well to filter your query results. + +For example, + +.. code-block:: graphql + :emphasize-lines: 2 + + query { + article (where: {author: {name: {_eq: "Sidney"}}}) { + id + title + } + } + +The behaviour of the comparision operators depends on whether the nested objects are a single object related via an +object relationship or an array of objects related via an array relationship. + +- In case of an **object relationship**, a row will be returned if the single nested object satisfies the defined + condition. +- In case of an **array relationship**, a row will be returned if **any of the nested objects** satisfy the defined + condition. + +Let's look at a few use cases based on the above: + +Fetch if the single nested object defined via an object relationship satisfies a condition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Example: +~~~~~~~~ +Fetch all articles whose author's name starts with "A": + +.. graphiql:: + :view_only: + :query: + { + article ( + where: { + author: { + name: { _similar: "A%"} + } + } + ) { + id + title + author { + name + } + } + } + :response: + { + "data": { + "article": [ + { + "id": 1, + "title": "sit amet", + "author": { + "name": "Anjela" + } + }, + { + "id": 3, + "title": "amet justo morbi", + "author": { + "name": "Anjela" + } + }, + { + "id": 4, + "title": "vestibulum ac est", + "author": { + "name": "Amii" + } + }, + { + "id": 12, + "title": "volutpat quam pede", + "author": { + "name": "Amii" + } + }, + { + "id": 13, + "title": "vulputate elementum", + "author": { + "name": "April" + } + }, + { + "id": 20, + "title": "eu nibh", + "author": { + "name": "April" + } + }, + { + "id": 5, + "title": "ut blandit", + "author": { + "name": "Amii" + } + }, + { + "id": 17, + "title": "montes nascetur ridiculus", + "author": { + "name": "Amii" + } + }, + { + "id": 19, + "title": "pede venenatis", + "author": { + "name": "Amii" + } + } + ] + } + } + + +Fetch if **any** of the nested objects defined via an array relationship satisfy a condition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Example: +~~~~~~~~ +Fetch all authors which have written at least one article which is rated 1 + +.. graphiql:: + :view_only: + :query: + { + author( + where: { + articles: {rating: {_eq: 1}} + } + ) { + id + name + articles { + title + rating + } + } + } + :response: + { + "data": { + "author": [ + { + "id": 1, + "name": "Justin", + "articles": [ + { + "title": "sem duis aliquam", + "rating": 1 + }, + { + "title": "vel dapibus at", + "rating": 4 + } + ] + }, + { + "id": 4, + "name": "Anjela", + "articles": [ + { + "title": "sit amet", + "rating": 1 + }, + { + "title": "amet justo morbi", + "rating": 4 + } + ] + }, + { + "id": 3, + "name": "Sidney", + "articles": [ + { + "title": "sapien ut", + "rating": 1 + }, + { + "title": "turpis eget", + "rating": 3 + }, + { + "title": "congue etiam justo", + "rating": 4 + } + ] + } + ] + } + } + +Fetch if **all** of the nested objects defined via an array relationship satisfy a condition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As by default a row is returned if any of the nested objects satisfy a condition, to achieve the above we need to frame +the ``where`` expression as ``{_not: {inverse-of-condition}}``. This reads as: fetch if not(any of the nested objects +satisfy the inverted condition) i.e. all of the nested objects satisfy the condition. + +For example, + ++---------------------------------------+-----------------------------------------------+ +| condition | where expression | ++=======================================+===============================================+ +| ``{object: {field: {_eq: "value"}}}`` | ``{_not: {object: {field: {_neq: "value"}}}`` | ++---------------------------------------+-----------------------------------------------+ +| ``{object: {field: {_gt: "value"}}}`` | ``{_not: {object: {field: {_lte: "value"}}}`` | ++---------------------------------------+-----------------------------------------------+ + +Example: +~~~~~~~~ +Fetch all authors which have all of their articles published i.e. have ``{is_published {_eq: true}``. + +.. graphiql:: + :view_only: + :query: + { + author ( + where: { + _not: { + articles: {is_published: {_neq: true}} + } + } + ) { + id + name + articles { + title + is_published + } + } + } + :response: + { + "data": { + "author": [ + { + "id": 1, + "name": "Justin", + "articles": [ + { + "title": "vel dapibus at", + "is_published": true + }, + { + "title": "sem duis aliquam", + "is_published": true + } + ] + }, + { + "id": 2, + "name": "Beltran", + "articles": [ + { + "title": "a nibh", + "is_published": true + }, + { + "title": "sit amet", + "is_published": true + } + ] + }, + { + "id": 4, + "name": "Anjela", + "articles": [ + { + "title": "sit amet", + "is_published": true + }, + { + "title": "amet justo morbi", + "is_published": true + } + ] + }, + { + "id": 8, + "name": "April", + "articles": [ + { + "title": "vulputate elementum", + "is_published": true + }, + { + "title": "eu nibh", + "is_published": true + } + ] + } + ] + } + } + + +Fetch if **none** of the nested objects defined via an array relationship satisfy a condition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As by default a row is returned if any of the nested objects satisfy a condition, to achieve the above we need to frame +the ``where`` expression as ``{_not: {condition}}``. This reads as: fetch if not(any of the nested objects +satisfy the condition) i.e. none of the nested objects satisy the condition. + +For example, + ++---------------------------------------+----------------------------------------------+ +| condition | where expression | ++=======================================+==============================================+ +| ``{object: {field: {_eq: "value"}}}`` | ``{_not: {object: {field: {_eq: "value"}}}`` | ++---------------------------------------+----------------------------------------------+ +| ``{object: {field: {_gt: "value"}}}`` | ``{_not: {object: {field: {_gt: "value"}}}`` | ++---------------------------------------+----------------------------------------------+ + +Example: +~~~~~~~~ +Fetch all authors which have none of their articles published i.e. have ``{is_published {_eq: true}``. + +.. graphiql:: + :view_only: + :query: + { + author ( + where: { + _not: { + articles: {is_published: {_eq: true}} + } + } + ) { + id + name + articles { + title + is_published + } + } + } + :response: + { + "data": { + "author": [ + { + "id": 7, + "name": "Berti", + "articles": [ + { + "title": "ipsum primis in", + "is_published": false + } + ] + }, + { + "id": 10, + "name": "Lyndsay", + "articles": [ + { + "title": "dui proin leo", + "is_published": false + } + ] + } + ] + } + } + + + + diff --git a/docs/graphql/manual/schema/relationships/index.rst b/docs/graphql/manual/schema/relationships/index.rst index a6ddc170103..d7a92cc97a2 100644 --- a/docs/graphql/manual/schema/relationships/index.rst +++ b/docs/graphql/manual/schema/relationships/index.rst @@ -12,7 +12,8 @@ Each relationship has a name which is used to refer to the nested objects in que an ``author`` and "``author``" of an ``article``. .. note:: - You can also simulate many-to-many relationships by creating what are typically known as ``bridge`` or ``through`` tables. See :ref:`many-to-many-relationships` + You can also simulate many-to-many relationships by creating what are typically known as ``bridge`` + tables. See :ref:`many-to-many-relationships` Creating relationships ---------------------- @@ -248,7 +249,10 @@ Here are examples to create relationships using the two methods: Many-to-many relationships ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Many-to-many relationships can be simulated by creating tables typically called as ``bridge`` or ``through`` or ``joining`` tables. Let's use a different example from the one above to create such a relationship - say your schema has products and categories. A product can belong to many categories and each category can have many products. Our objective is to fetch a list of products and the possibly many categories each product belongs to. +Many-to-many relationships can be simulated by creating tables typically called as ``bridge`` or ``junction`` or +``join`` tables. Let's use a different example from the one above to create such a relationship - say your schema +has products and categories. A product can belong to many categories and each category can have many products. Our +objective is to fetch a list of products and the possibly many categories each product belongs to. **Create bridge or through table** @@ -276,7 +280,8 @@ To capture the association between products and categories, we'll create the fol category_id INT ) -This table sits between the two tables involved in the many-to-many relationship and captures possible permutations of their association. Next, we'll link the data in the ``product`` and ``category`` tables via the bridge table. +This table sits between the two tables involved in the many-to-many relationship and captures possible permutations +of their association. Next, we'll link the data in the ``product`` and ``category`` tables via the bridge table. **Add foreign-key constraints** @@ -289,10 +294,13 @@ Add the following constraints: Add the following relationships: -- modify the ``product`` table to add an array relationship between ``products_categories`` :: ``product_id`` -> ``id``, named ``prod_categories``. -- modify the ``products_categories`` table to add an object relationship between ``category_id`` -> ``category`` :: ``id``, named ``category``. +- modify the ``product`` table to add an array relationship between ``products_categories`` :: ``product_id`` -> + ``id``, named ``prod_categories``. +- modify the ``products_categories`` table to add an object relationship between ``category_id`` -> ``category`` :: + ``id``, named ``category``. -We can now fetch a list of products and a list of categories each product belongs to by leveraging the above relationships: +We can now fetch a list of products and a list of categories each product belongs to by leveraging the above +relationships: .. graphiql:: :view_only: @@ -343,9 +351,14 @@ We can now fetch a list of products and a list of categories each product belong } } -If you need to fetch a list of categories and a list of products belonging to each category, you just have to create the relationships the other way around i.e. in ``category`` table, an array relationship between ``products_categories`` :: ``product_id`` -> ``id`` and in the ``products_categories`` table, an object relationship between ``product_id`` -> ``product`` :: ``id``. +If you need to fetch a list of categories and a list of products belonging to each category, you just have to create +the relationships the other way around. i.e. in ``category`` table, an array relationship named ``cat_products`` between +``products_categories`` :: ``product_id`` -> ``id`` and in the ``products_categories`` table, an object relationship +named ``product`` between ``product_id`` -> ``product`` :: ``id``. -The intermediate join table is important as you might add more columns to it over time. For example, the ``products_categories`` table may have a column like ``created_at``. So, the above query then changes to: +The intermediate fields ``prod_categories`` & ``cat_products`` are important as they can be used to fetch extra +information about the relationship. For example, you can have a column like ``created_at`` in the ``products_categories`` +table which you can fetch as follows: .. code-block:: graphql @@ -354,7 +367,7 @@ The intermediate join table is important as you might add more columns to it ove id prod_name prod_categories { - created_at, + created_at category { cat_name }