Postgres: Create Relationships
Introduction
A relationship from one table/view/Native Query to another can be created by defining a link between a column of the table/view/Native Query to a column of the other table/view/Native Query.
Typically, relationships between tables are defined using foreign-key constraints. But in some cases, it might not be possible to use foreign-key constraints to create the relationship. For example, while trying to create a relationship involving a view or Native Query since foreign-keys cannot be created on them.
Using foreign keys
Say we created two tables, authors(id, name)
and articles(id, title, content, rating, author_id)
.
Let us now connect these tables to enable nested queries using a foreign-key:
Step 1: Add foreign-key constraint
Let's add a foreign-key constraint to the author_id
column in the articles
table.
- Console
- CLI
- API
In the Console, navigate to the Modify
tab of the articles
table. Click the Add
button in the Foreign Keys section
and configure the author_id
column as a foreign-key for the id
column in the authors
table:
Create a migration manually and add the
following SQL statement to the up.sql
file:
ALTER TABLE articles
ADD FOREIGN KEY (author_id) REFERENCES authors(id);
Add the following statement to the down.sql
file in case you need to
roll back the above statement:
ALTER TABLE articles
DROP CONSTRAINT articles_author_id_fkey;
Apply the migration by running:
hasura migrate apply
You can add a foreign-key constraint using the run_sql schema API:
POST /v2/query HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "run_sql",
"args": {
"source": "<db_name>",
"sql": "ALTER TABLE articles ADD FOREIGN KEY (author_id) REFERENCES authors(id);"
}
}
Step 2: Create an object relationship
Each article has one author. This is an object relationship
.
- Console
- CLI
- API
The Console infers potential relationships using the foreign-key created above and recommends these in the
Relationships
tab of the articles
table.
Add an object relationship
named author
for the articles
table as shown here:
You can add an object relationship in the tables.yaml
file inside the metadata
directory:
- table:
schema: public
name: articles
object_relationships:
- name: author
using:
foreign_key_constraint_on: author_id
- table:
schema: public
name: authors
Apply the Metadata by running:
hasura metadata apply
You can create an object relationship by using the pg_create_object_relationship Metadata API:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "pg_create_object_relationship",
"args": {
"source": "<db_name>",
"table": "articles",
"name": "author",
"using": {
"foreign_key_constraint_on": "author_id"
}
}
}
We can now run a nested object query that is based on this object relationship
.
Fetch a list of articles and each article's author:
Step 3: Create an array relationship
An author can write multiple articles. This is an array relationship
.
You can add an array relationship
in the same fashion as an object relationship
as shown above.
- Console
- CLI
- API
On the Console, add an array relationship
named articles
for the authors
table as shown here:
We can now run a nested object query that is based on this array relationship
.
You can add an array relationship in the tables.yaml
file inside the metadata
directory:
- table:
schema: public
name: articles
object_relationships:
- name: author
using:
foreign_key_constraint_on: author_id
- table:
schema: public
name: authors
array_relationships:
- name: articles
using:
foreign_key_constraint_on:
column: author_id
table:
schema: public
name: articles
Apply the Metadata by running:
hasura metadata apply
You can create an array relationship by using the pg_create_array_relationship Metadata API:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "pg_create_array_relationship",
"args": {
"source": "<db_name>",
"table": "authors",
"name": "articles",
"using": {
"foreign_key_constraint_on" : {
"table" : "articles",
"column" : "author_id"
}
}
}
}
Fetch a list of authors and a nested list of each author's articles:
Using manual relationships
Let's say you have a table authors (id, name)
and a view author_avg_rating (id, avg)
which has the average rating of articles for each author.
Let us now create an object relationship
called avg_rating
from the authors
table to the author_avg_rating
view
using a manual relationship:
- Console
- CLI
- API
Step 1: Open the manual relationship section
- Open the Console and navigate to the
Data -> authors -> Relationships
tab. - Click on the
Add Relationship
button:
Step 2: Fill in the relationships details
Once the widget is open, fill in the name of the relationship and pick a reference source
This will open up a "details" section below where you can fill in the rest of the relationship definition
Step 3: Create the relationship
Now click on the Create Relationship
button to proceed.
You can add a manual relationship in the tables.yaml
file inside the metadata
directory:
- table:
schema: public
name: articles
- table:
schema: public
name: authors
object_relationships:
- name: avg_rating
using:
manual_configuration:
remote_table:
schema: public
name: author_average_rating
column_mapping:
id: author_id
- table:
schema: public
name: author_average_rating
Apply the Metadata by running:
hasura metadata apply
You can add a manual relationship by using the pg_create_object_relationship Metadata API:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "pg_create_object_relationship",
"args": {
"source": "<db_name>",
"table": "authors",
"name": "avg_rating",
"using": {
"manual_configuration": {
"remote_table": "author_average_rating",
"column_mapping": {
"id": "author_id"
}
}
}
}
}
We can now run a nested object query that is based on this object relationship
.
Fetch a list of authors with the average rating of their articles:
Tracking existing relationships inferred via foreign-keys
As mentioned in the Introduction section above, relationships can be inferred via foreign-keys that exist in your database:
- Console
- CLI
- API
The Console infers potential relationships using existing foreign-keys and recommends these on the Data -> Schema
page
You can choose to track the relationships individually using the Track
buttons or hit the Track all
button to track
all the inferred relationships in one go.
You can add relationships in the tables.yaml
file inside the metadata
directory:
- table:
schema: public
name: articles
object_relationships:
- name: author
using:
foreign_key_constraint_on: author_id
- table:
schema: public
name: authors
array_relationships:
- name: articles
using:
foreign_key_constraint_on:
column: author_id
table:
schema: public
name: articles
Apply the Metadata by running:
hasura metadata apply
You can create multiple relationships by using the pg_create_object_relationship and the pg_create_array_relationship Metadata APIs:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "bulk",
"args": [
{
"type": "pg_create_object_relationship",
"args": {
"source": "<db_name>",
"table": "articles",
"name": "author",
"using": {
"foreign_key_constraint_on": "author_id"
}
}
},
{
"type": "pg_create_array_relationship",
"args": {
"source": "<db_name>",
"table": "authors",
"name": "articles",
"using": {
"foreign_key_constraint_on" : {
"table" : "articles",
"column" : "author_id"
}
}
}
}
]
}
Tracking relationships between tables and Native Queries
As mentioned in the Introduction section above, a relationship from a table to a Native Query can only be set up manually.
- API
Given a table named articles
and an existing Native Query named get_author
,
we can set up a relationship between the two.
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type": "bulk",
"args": [
{
"type": "pg_create_object_relationship",
"args": {
"source": "<db_name>",
"table": "articles",
"name": "author",
"using": {
"manual_configuration": {
"remote_native_query": "get_author",
"column_mapping": {
"id": "author_id"
}
}
}
}
}
]
}