graphql-engine/docs/graphql/manual/schema/relationships/database-modelling/many-to-many.rst

196 lines
4.7 KiB
ReStructuredText
Raw Normal View History

Modelling many-to-many table relationships
==========================================
A many-to-many relationship between two tables can be established by creating a table typically called as ``bridge``
or ``junction`` or ``join`` table and adding foreign-key constraints from it to the original tables.
Say we have the following two tables in our database schema:
.. code-block:: sql
article (
id INT PRIMARY KEY,
title TEXT
...
)
tag (
id INT PRIMARY KEY,
tag_value TEXT
...
)
These two tables are related via a ``many-to-many`` relationship. i.e:
- an ``article`` can have many ``tags``
- a ``tag`` has many ``articles``
This ``many-to-many`` relationship can be established in the database by:
1. Creating a bridge table called ``article_tag`` with the following structure:
.. code-block:: sql
article_tag (
id INT PRIMARY KEY
article_id INT
tag_id INT
...
)
2. Adding foreign-key constraints from the ``article_tag`` table to:
- the ``article`` table using the ``article_id`` and ``id`` columns of the tables respectively
- the ``tag`` table using the ``tag_id`` and ``id`` columns of the tables respectively
The table ``article_tag`` sits between the two tables involved in the many-to-many relationship and captures possible
permutations of their association via the foreign-keys.
To access the nested objects via the GraphQL API, :doc:`create the following relationships <../create>`:
- Array relationship, ``article_tags`` from ``article`` table using ``article_tag :: article_id -> id``
- Object relationship, ``tag`` from ``article_tag`` table using ``tag_id -> tag :: id``
- Array relationship, ``tag_articles`` from ``tag`` table using ``article_tag :: tag_id -> id``
- Object relationship, ``article`` from ``article_tag`` table using ``article_id -> article :: id``
We can now:
- fetch a list of articles with their tags:
.. graphiql::
:view_only:
:query:
query {
article {
id
title
article_tags {
tag {
id
tag_value
}
}
}
}
:response:
{
"data": {
"article": [
{
"id": 1,
"title": "sit amet",
"article_tags": [
{
"tag": {
"id": 1,
"tag_value": "mystery"
}
},
{
"tag": {
"id": 2,
"tag_value": "biography"
}
}
]
},
{
"id": 2,
"title": "a nibh",
"article_tags": [
{
"tag": {
"id": 2,
"tag_value": "biography"
}
},
{
"tag": {
"id": 5,
"tag_value": "technology"
}
}
]
}
]
}
}
- fetch a list of tags with their articles:
.. graphiql::
:view_only:
:query:
query {
tag {
id
tag_value
tag_articles {
article {
id
title
}
}
}
}
:response:
{
"data": {
"tag": [
{
"id": 1,
"tag_value": "mystery",
"tag_articles": [
{
"article": {
"id": 1,
"title": "sit amet"
}
}
]
},
{
"id": 2,
"tag_value": "biography",
"tag_articles": [
{
"article": {
"id": 1,
"title": "sit amet"
}
},
{
"article": {
"id": 2,
"title": "a nibh"
}
}
]
}
]
}
}
.. note::
The intermediate fields ``article_tags`` & ``tag_articles`` are important as they can be used to fetch extra
information about the relationship. For example, you can have a column like ``tagged_at`` in the ``article_tag``
table which you can fetch as follows:
.. code-block:: graphql
query {
article {
id
title
article_tags {
tagged_at
tag {
tag_value
}
}
}
}