You can define many-to-many and one-to-many relationships in Fauna using the @relation
directive in your GraphQL schema. However, the directive does not work for relationships from a type to itself.
To create such self-referential relationships yourself, you can model the relationships in GraphQL using an intermediate “link table” type.
Many-to-Many Example
Fauna creates many-to-many relationships by creating an intermediate Collection and abstracting the implementation out of the way for you. It can be implemented by hand in a similar way.
Consider the following example schema:
type Item {
name: String!
children: [ItemLink]! @relation(name: "item_children")
parents: [ItemLink]! @relation(name: "item_parents")
}
type ItemLink {
parent: Item! @relation(name: "item_children")
child: Item! @relation(name: "item_parents")
}
When you create relationships between the parent/child items, you have to create the “links” yourself. In this example, a nested mutation is used to create one item and its children. To do so, the mutation creates a list of ItemLink
, each one then creating an Item
as the child.
The new items can be queried by explicitly selecting all of the links and then selecting the child field of the link.
Uniqueness
To ensure that the same link is not made more than once, manually create a unique compound index on the joining fields. For this example it could be:
CreateIndex({
name: "unique_itemLink_parent_child",
unique: true,
serialized: true,
source: Collection("ItemLink"),
terms: [
{ field: ["data", "parent"] },
{ field: ["data", "child"] }
]
})
One-to-Many Example
We can use the same "link table" technique to define a one-to-many relationship.
type Item {
name: String!
children: [ItemLink]! @relation(name: "item_children")
parent: ItemLink! @relation(name: "item_parents")
}
type ItemLink {
parent: Item! @relation(name: "item_children")
child: Item! @relation(name: "item_parents") @unique
}
Here, we have specified that an Item has exactly one parent. We have changed the type of Item.parent
field from [ItemLink]!
to ItemLink!
.
Conversely, this means that there can only ever be one link to an Item as a child. We added the @unique
constraint to the ItemLink.child
field.