Relationships
|
This is the documentation of the GraphQL Library version 7. For the long-term support (LTS) version 5, refer to GraphQL Library version 5 LTS. |
Without relationships, your type definitions represent a collection of disconnected nodes with little value. Adding relationships to your data model gives your data the context that it needs to run complex queries across wide sections of your graph.
This section describes how to model and interact with relationships in your GraphQL schema:
-
Read along to find out about the anatomy of a relationship.
-
Learn about the different operations on relationships in relationship operations.
-
Learn about the different ways of modeling relationships in the GraphQL schema in modeling relationships.
-
Learn about the concept of single relationships.
-
See how to use interfaces and unions with relationships.
Data model
Take the following graph as an example in which the Person and Movie types are connected by a single relationship type, ACTED_IN.
The relationship has a property roles which describes the different roles that an actor played in a movie.
Writing type definitions
Nodes
To create the graph using the Neo4j GraphQL Library, first define the two node types together with their fields.
In order for these types to be represented as nodes in the graph, decorate them with the @node directive.
type Person @node {
name: String!
}
type Movie @node {
title: String!
released: Int!
}
Relationships
Define the relationships between the two types by adding special relationship fields using the @relationship directive.
A Person can act in multiple movies, and a Movie can have multiple actors. Conceptually this is a many-to-many relationship and you can model it by using list types for both relationship fields, on both sides of the relationship.
type Person @node {
name: String!
actedInMovies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}
type Movie @node {
title: String!
released: Int!
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}
Anatomy of a relationship
Relationship direction
The direction argument is relative to the node type on which the @relationship directive is used.
The value IN means that the relationship points to this node while OUT means that the relationship originates from this node.
In the example graph, Person-[ACTED_IN]→Movie means that the relationship of type ACTED_IN points to a Movie, therefore the Movie.actors relationship field has direction: IN.
Conversely, the Actors.actedInMovies relationship field has direction: OUT because the relationship originates from a Person and points to a Movie.
To figure out whether the direction argument of the @relationship directive should be IN or OUT it can be helpful to visualize your graph like in the diagram above and model the direction of the arrows.
Relationship properties
The ACTED_IN relationship has a property roles which describes the different roles that an actor played in a movie.
To model this:
-
Add an
ActedIntype decorated with the@relationshipPropertiesdirective, containing the desired relationship properties. -
Set the
@relationshipdirective’spropertiesargument value toActedIn. This can be done on both or either side of the relationship, depending on where you want to query the relationship properties from.
type ActedIn @relationshipProperties {
roles: [String!]
}
type Person @node {
name: String!
actedIn: [Movie!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: OUT)
}
type Movie @node {
title: String!
released: Int!
actors: [Person!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: IN)
}
|
Relationship properties fields can only be primitive types or their list variants. You cannot have relationship properties of a complex type such as object types or interfaces. |