Skip to main content
Version: v3.x (DDN)

Relationships

Introduction

Defining a relationship allows you to make queries across linked information.

Relationships are defined in metadata from an object type, to a model or command.

This enables you to create complex queries, where you can fetch related data in a single query.

By defining a Relationship object, all models or commands whose output type is the source object type defined in the relationship will now have a connection to the target model or command.

So from this relationship definition, all models or commands in the supergraph whose output type is the orders object type will now have a connection to the customers model via the customer relationship field on the orders type.

So, as in example 1 below, you can now fetch the customer when you query orders. Note that also, if you had, for instance an arbitrary command such as getCustomerLastOrder which also returned an order from a customer id, you can now also return the customer's details for that returned order in the same single query from this relationship.

How relationships work

Lifecycle

You can automatically add foreign-key relationships to your metadata using the CLI.

Additionally, you can manually define relationships from an object type to a model or command in your metadata using the VS Code extension. The extension knows about your data sources and can help you write relationships more efficiently.

Simply start by typing a delimiter (---) at the end of a model's metadata file and start typing Relationship. The extension will provide you with auto-completion, syntax highlighting, and error checking as you write your relationships. At any point in the process, you can type Ctrl + Space to see the available options and tab through the fields to fill in the required information.

To make a relationship available in your supergraph, you'll need to create a new build using the CLI.

Examples

---
kind: Relationship
version: v1
definition:
name: customer
sourceType: orders
target:
model:
name: customers
subgraph: customers
relationshipType: Object
mapping:
- source:
fieldPath:
- fieldName: customerId
target:
modelField:
- fieldName: customerId
FieldDescriptionReference
kindIndicates that this object is defining a relationship between two data types or models.Relationship
versionSpecifies the version of the relationship's structure.RelationshipV1
definition.nameThe name of the relationship, representing the link between the source and target.RelationshipName
definition.sourceTypeDefines the source object type that the relationship starts from.CustomTypeName
definition.target.model.nameThe name of the target model to which the source is related.ModelName
definition.target.model.subgraphSpecifies the subgraph in which the target model resides.ModelRelationshipTarget
definition.target.model.relationshipTypeIndicates the type of relationship (Object or Array), determining whether one or many related items can be fetched.RelationshipType
definition.mappingDefines how fields from the source map to fields or arguments in the target, establishing the connection between them.RelationshipMapping

Object Type to a Model

As mentioned above, in an e-commerce context, you will likely have customers and orders, and you want to relate them so that when you query orders you can easily fetch the customer on that order.

To do this in DDN metadata for this example, you might have an orders model which returns an orders object type and you want to relate that to a customers model and whatever object type it returns.

Example: Fetch a list of orders along with the customer details for each order:

Here is the corresponding relationship configuration which enables this query:

kind: Relationship
version: v1
definition:
name: customer
sourceType: orders
target:
model:
name: customers
subgraph: customers
relationshipType: Object
mapping:
- source:
fieldPath:
- fieldName: customerId
target:
modelField:
- fieldName: customerId
description: The customer details for an order

Now, you can also retrieve the customer details for any model or command in your schema that returns the orders object type.

For convenience, this relationship configuration would best be located with your orders object type and model.

Object Type to a Command

Let's say you have a user object type in your graph, and also a command which responds with the current logged-in user information (say getLoggedInUserInfo). Now you can link these two, by defining a relationship from the user object type to getLoggedInUserInfo.

Let's say we name the relationship currentSession. Now you can make a single query from your client to get a user's data and their current session information.

Example: fetch a list of users and the current session information of each user:

Here is the corresponding relationship configuration which enables this query:

kind: Relationship
version: v1
definition:
name: currentSession
sourceType: user
target:
command:
name: getLoggedInUserInfo
subgraph: users
mapping:
- source:
fieldPath:
- fieldName: id
target:
argument:
argumentName: user_id
description: The current session information for the user

Command to Command

Hasura DDN also allows you to link commands together from a source type to query related data.

Example: fetch the result of one command and use it as input for another command:

And the corresponding relationship configuration which enables this query:

kind: Relationship
version: v1
definition:
name: shippingDetails
sourceType: trackOrder
target:
command:
name: getShippingDetails
subgraph: orders
mapping:
- source:
fieldPath:
- fieldName: trackingNumber
target:
argument:
argumentName: trackingNumber
description: The shipping details for an order based on its tracking number
VS Code extension assisted authoring

Relationships are written in your various HML files. If you're using a compatible editor (such as VS Code with the Hasura VS Code extension), assisted authoring will help you create relationships more efficiently. It will provide you with auto-completion, syntax highlighting, and error checking as you write your relationships.

The CLI also works to automatically track your relationships for you whenever you add or update a data connector.


Metadata structure

Relationship

Definition of a relationship on an OpenDD type which allows it to be extended with related models or commands.

KeyValueRequiredDescription
kindRelationshiptrue
versionv1true
definitionRelationshipV1trueDefinition of a relationship on an OpenDD type which allows it to be extended with related models or commands.

Example:

kind: Relationship
version: v1
definition:
name: Articles
sourceType: author
target:
model:
name: Articles
subgraph: null
relationshipType: Array
mapping:
- source:
fieldPath:
- fieldName: author_id
target:
modelField:
- fieldName: author_id
description: Articles written by an author

RelationshipV1

Definition of a relationship on an OpenDD type which allows it to be extended with related models or commands.

KeyValueRequiredDescription
nameRelationshipNametrueThe name of the relationship.
sourceTypeCustomTypeNametrueThe source type of the relationship.
targetRelationshipTargettrueThe target of the relationship.
mapping[RelationshipMapping]trueThe mapping configuration of source to target for the relationship.
descriptionstring / nullfalseThe description of the relationship. Gets added to the description of the relationship in the graphql schema.
deprecatedDeprecated / nullfalseWhether this relationship is deprecated. If set, the deprecation status is added to the relationship field's graphql schema.
graphqlRelationshipGraphQlDefinition / nullfalseConfiguration for how this relationship should appear in the GraphQL schema.

RelationshipGraphQlDefinition

The definition of how a relationship appears in the GraphQL API

KeyValueRequiredDescription
aggregateFieldNameFieldName / nullfalseThe field name to use for the field that represents an aggregate over the relationship

Deprecated

OpenDd configuration to indicate whether an object type field, relationship, model root field or command root field is deprecated.

KeyValueRequiredDescription
reasonstring / nullfalseThe reason for deprecation.

RelationshipMapping

Definition of a how a particular field in the source maps to a target field or argument.

KeyValueRequiredDescription
sourceRelationshipMappingSourcetrueThe source configuration for this relationship mapping.
targetRelationshipMappingTargettrueThe target configuration for this relationship mapping.

Example:

source:
fieldPath:
- fieldName: author_id
target:
modelField:
- fieldName: author_id

RelationshipMappingTarget

The target configuration for a relationship mapping.

Must have exactly one of the following fields:

KeyValueRequiredDescription
argumentArgumentMappingTargetfalseAn argument target for a relationship mapping.
modelField[RelationshipSourceFieldAccess]false

ArgumentMappingTarget

An argument target for a relationship mapping.

KeyValueRequiredDescription
argumentNameArgumentNametrue

ArgumentName

The name of an argument.

Value: string

RelationshipMappingSource

The source configuration for a relationship mapping.

Must have exactly one of the following fields:

KeyValueRequiredDescription
valueValueExpressionfalseAn expression which evaluates to a value that can be used in permissions and various presets.
fieldPath[RelationshipSourceFieldAccess]false

RelationshipSourceFieldAccess

A field access in a relationship mapping.

KeyValueRequiredDescription
fieldNameFieldNametrue

FieldName

The name of a field in a user-defined object type.

Value: string

ValueExpression

An expression which evaluates to a value that can be used in permissions and various presets.

Must have exactly one of the following fields:

KeyValueRequiredDescription
literalfalse
sessionVariablestringfalse

RelationshipTarget

The target for a relationship.

Must have exactly one of the following fields:

KeyValueRequiredDescription
modelModelRelationshipTargetfalseThe target model for a relationship.
commandCommandRelationshipTargetfalseThe target command for a relationship.

Example:

model:
name: Articles
subgraph: null
relationshipType: Array

CommandRelationshipTarget

The target command for a relationship.

KeyValueRequiredDescription
nameCommandNametrueThe name of the command.
subgraphstring / nullfalseThe subgraph of the target command. Defaults to the current subgraph.

CommandName

The name of a command.

Value: string

ModelRelationshipTarget

The target model for a relationship.

KeyValueRequiredDescription
nameModelNametrueThe name of the data model.
subgraphstring / nullfalseThe subgraph of the target model. Defaults to the current subgraph.
relationshipTypeRelationshipTypetrueType of the relationship - object or array.
aggregateModelRelationshipTargetAggregate / nullfalseHow to aggregate over the relationship. Only valid for array relationships

ModelRelationshipTargetAggregate

Which aggregate expression to use to aggregate the array relationship.

KeyValueRequiredDescription
aggregateExpressionAggregateExpressionNametrueThe name of the aggregate expression that defines how to aggregate across the relationship.
descriptionstring / nullfalseThe description of the relationship aggregate. Gets added to the description of the aggregate field in the GraphQL schema

AggregateExpressionName

The name of an aggregate expression.

Value: string

RelationshipType

Type of the relationship.

One of the following values:

ValueDescription
ObjectSelect one related object from the target.
ArraySelect multiple related objects from the target.

ModelName

The name of data model.

Value: string

CustomTypeName

The name of a user-defined type.

Value: string

RelationshipName

The name of the GraphQL relationship field.

Value: string