mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
adds content for many-to-many relationships (#807)
This commit is contained in:
parent
405f5edb34
commit
82e8d45bf9
@ -9,7 +9,10 @@ Relationships can be of two types:
|
||||
- one-to-many or ``array relationships``. For example, one author can write many articles
|
||||
|
||||
Each relationship has a name which is used to refer to the nested objects in queries. For example, "``articles``" of
|
||||
an ``author`` and "``author``" of an ``article``
|
||||
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`
|
||||
|
||||
Creating relationships
|
||||
----------------------
|
||||
@ -241,6 +244,124 @@ 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.
|
||||
|
||||
**Create bridge or through table**
|
||||
|
||||
This is the intial schema we are working with:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
product (
|
||||
id INT PRIMARY KEY,
|
||||
prod_name TEXT
|
||||
)
|
||||
|
||||
category (
|
||||
id INT PRIMARY KEY,
|
||||
cat_name TEXT
|
||||
)
|
||||
|
||||
To capture the association between products and categories, we'll create the following table:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
products_categories (
|
||||
id INT PRIMARY KEY,
|
||||
product_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.
|
||||
|
||||
**Add foreign-key constraints**
|
||||
|
||||
Add the following constraints:
|
||||
|
||||
- ``products_categories`` :: ``product_id`` -> ``product`` :: ``id``
|
||||
- ``products_categories`` :: ``category_id`` -> ``category`` :: ``id``
|
||||
|
||||
**Add 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 ``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:
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
product {
|
||||
id
|
||||
prod_name
|
||||
prod_categories {
|
||||
category {
|
||||
cat_name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"product": [
|
||||
{
|
||||
"id": 1,
|
||||
"prod_name": "pencil",
|
||||
"prod_categories": [
|
||||
{
|
||||
"category": {
|
||||
"cat_name": "stationary"
|
||||
}
|
||||
},
|
||||
{
|
||||
"category": {
|
||||
"cat_name": "weapon"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"prod_name": "bottle",
|
||||
"prod_categories": [
|
||||
{
|
||||
"category": {
|
||||
"cat_name": "kitchen"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
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``.
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: graphql
|
||||
|
||||
query {
|
||||
product {
|
||||
id
|
||||
prod_name
|
||||
prod_categories {
|
||||
created_at,
|
||||
category {
|
||||
cat_name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Renaming relationships
|
||||
----------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user