update docs (#860)

* add $ before commands in server flag reference docs

* add deploy to AWS RDS blog link to guides in docs

* fix pagination expressionin reference docs

* update many-to-many relationship docs

* add _not operator + filtering over relationships docs
This commit is contained in:
Rikin Kachhia 2018-10-26 08:29:36 +05:30 committed by Shahidh K Muhammed
parent 7fa6203b4f
commit dada14b1ad
6 changed files with 576 additions and 24 deletions

View File

@ -241,4 +241,5 @@ PaginationExp
.. parsed-literal:: .. parsed-literal::
limit: Integer [offset: Integer] limit: Integer
[offset: Integer]

View File

@ -5,7 +5,7 @@ Every GraphQL engine command is structured as:
.. code-block:: bash .. code-block:: bash
graphql-engine <server-flags> serve <command-flags> $ graphql-engine <server-flags> serve <command-flags>
Server flags Server flags
^^^^^^^^^^^^ ^^^^^^^^^^^^

View File

@ -3,6 +3,7 @@ Guides: Deployment
- :doc:`Deploy on Digital Ocean using Docker <digital-ocean>` - :doc:`Deploy on Digital Ocean using Docker <digital-ocean>`
- :doc:`Digital Ocean One-click App <digital-ocean-one-click>` - :doc:`Digital Ocean One-click App <digital-ocean-one-click>`
- `Blog: Instant GraphQL on AWS RDS <https://blog.hasura.io/instant-graphql-on-aws-rds-1edfb85b5985>`__
.. note:: .. note::
The above are guides to deploy Hasura GraphQL engine on some specific platforms. The above are guides to deploy Hasura GraphQL engine on some specific platforms.

View File

@ -6,6 +6,7 @@ Deployment guides
- :doc:`Deploy on Digital Ocean using Docker <deployment/digital-ocean>` - :doc:`Deploy on Digital Ocean using Docker <deployment/digital-ocean>`
- :doc:`Digital Ocean One-click App <deployment/digital-ocean-one-click>` - :doc:`Digital Ocean One-click App <deployment/digital-ocean-one-click>`
- `Blog: Instant GraphQL on AWS RDS <https://blog.hasura.io/instant-graphql-on-aws-rds-1edfb85b5985>`__
.. note:: .. note::
The above are guides to deploy Hasura GraphQL engine on some specific platforms. The above are guides to deploy Hasura GraphQL engine on some specific platforms.

View File

@ -1,11 +1,11 @@
Filter query results / search queries Filter query results / search queries
===================================== =====================================
You can use the ``where`` argument in your queries to filter the results based on a fields values (including in a You can use the ``where`` argument in your queries to filter results based on some fields values (even
nested objects fields). You can even use multiple filters in the same ``where`` clause using the ``_and`` or the nested objects' fields). You can even use multiple filters in the same ``where`` clause using the ``_and`` or the
``_or`` operators. ``_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 .. code-block:: graphql
:emphasize-lines: 3 :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 You can also use nested objects` fields to filter rows from a table and also filter the nested objects as well.
authors who have articles with a rating greater than 4:
For example, to fetch a list of authors who have articles with a rating greater than 4 along with those articles:
.. code-block:: graphql .. code-block:: graphql
:emphasize-lines: 3 :emphasize-lines: 2,5
query { query {
author( author (where: {articles: {rating: {_gt: 4}}}) {
where: {articles: {rating: {_gt: 4}}}
) {
id id
name 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 Here ``_eq`` and ``_gt`` are examples of comparison operators that can be used in the ``where`` argument to filter on
equality. Lets take a look at different operators that can be used to filter results and the field types these equality.
operators are compatible with.
Lets take a look at different operators that can be used to filter results and other advanced use cases:
Equality operators (_eq and _neq) 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 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 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 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 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. 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 Example: _and
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
Fetch a list of articles published in a specific time-frame (for example: in year 2017): 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
}
]
}
]
}
}

View File

@ -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``. an ``author`` and "``author``" of an ``article``.
.. note:: .. 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 Creating relationships
---------------------- ----------------------
@ -248,7 +249,10 @@ Here are examples to create relationships using the two methods:
Many-to-many relationships 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** **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 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** **Add foreign-key constraints**
@ -289,10 +294,13 @@ Add the following constraints:
Add the following relationships: Add the following relationships:
- modify the ``product`` table to add an array relationship between ``products_categories`` :: ``product_id`` -> ``id``, named ``prod_categories``. - modify the ``product`` table to add an array relationship between ``products_categories`` :: ``product_id`` ->
- modify the ``products_categories`` table to add an object relationship between ``category_id`` -> ``category`` :: ``id``, named ``category``. ``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:: .. graphiql::
:view_only: :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 .. code-block:: graphql
@ -354,7 +367,7 @@ The intermediate join table is important as you might add more columns to it ove
id id
prod_name prod_name
prod_categories { prod_categories {
created_at, created_at
category { category {
cat_name cat_name
} }