Back to Graphql Engine

Modeling One-to-Many Table Relationships

docs/docs/schema/common-patterns/data-modeling/one-to-many.mdx

2.48.165.0 KB
Original Source

import GraphiQLIDE from '@site/src/components/GraphiQLIDE';

Modeling One-to-Many Table Relationships

Introduction

A one-to-many relationship between two tables can be established via a foreign key constraint.

Say we have the following two tables in our database schema:

sql
authors (
  id SERIAL PRIMARY KEY,
  name TEXT
)

articles (
  id SERIAL PRIMARY KEY,
  author_id INT
  title TEXT
  ...
)

These two tables are related via a one-to-many relationship. i.e:

  • an author can have many articles
  • an article has one author

Step 1: Set up a table relationship in the database

This one-to-many relationship can be established in the database by:

  1. Adding a foreign key constraint from the articles table to the authors table using the author_id and id columns of the tables respectively.

This will ensure that the value of author_id column in the articles table is present in the id column of the authors table.

Step 2: Set up GraphQL relationships

To access the nested objects via the GraphQL API, create the following relationships:

  • Array relationship, articles from authors table using articles :: author_id -> id
  • Object relationship, author from articles table using author_id -> authors :: id

Query using one-to-many relationships

We can now:

  • fetch a list of authors with their articles:

<GraphiQLIDE query={query { authors { id name articles { id title } } }} response={{ "data": { "authors": [ { "id": 1, "name": "Justin", "articles": [ { "id": 15, "title": "vel dapibus at" }, { "id": 16, "title": "sem duis aliquam" } ] }, { "id": 2, "name": "Beltran", "articles": [ { "id": 2, "title": "a nibh" }, { "id": 9, "title": "sit amet" } ] } ] } }} />

  • fetch a list of articles with their author:

<GraphiQLIDE query={query { articles { id title author { id name } } }} response={{ "data": { "articles": [ { "id": 1, "title": "sit amet", "author": { "id": 4, "name": "Anjela" } }, { "id": 2, "title": "a nibh", "author": { "id": 2, "name": "Beltran" } } ] } }} />

Insert using one-to-many relationships

We can now:

  • insert an author with their articles where the author might already exist (assume unique name for author):

<GraphiQLIDE query={mutation UpsertAuthorWithArticles { insert_author(objects: { name: "Felix", articles: { data: [ { title: "Article 1", content: "Article 1 content" }, { title: "Article 2", content: "Article 2 content" } ] } }, on_conflict: { constraint: author_name_key, update_columns: [name] } ) { returning { name articles { title content } } } }} response={{ "data": { "insert_author": { "returning": [ { "name": "Felix", "articles": [ { "title": "Article 1", "content": "Article 1 content" }, { "title": "Article 2", "content": "Article 2 content" } ] } ] } } }} />

  • insert articles with their author where the author might already exist (assume unique name for author):

<GraphiQLIDE query={mutation upsertArticleWithAuthors { insert_article(objects: [ { title: "Article 1", content: "Article 1 content", author: { data: { name: "Alice" }, on_conflict: { constraint: author_name_key, update_columns: [name] } } }, { title: "Article 2", content: "Article 2 content", author: { data: { name: "Alice" }, on_conflict: { constraint: author_name_key, update_columns: [name] } } } ]) { returning { title content author { name } } } }} response={{ "data": { "insert_article": { "returning": [ { "title": "Article 1", "content": "Article 1 content", "author": { "name": "Alice" } }, { "title": "Article 2", "content": "Article 2 content", "author": { "name": "Alice" } } ] } } }} />

:::info Note

You can avoid the on_conflict clause if you will never have conflicts.

:::