Joining Data Sources

Grafbase allows you to join data from one data source onto data returned from a different data source.

This is done by adding a field and marking that field as a join using the join function. This function takes the query you wish to use to fulfil the join, including any parameters require to resolve that query. These parameters can either be hard coded, or can use pull in fields from the type containing the join - all the fields of the current type are implicitly available using GraphQL variable syntax.

For example if you have a Stripe data source and an Orb data source, and you want to add an orbCustomer field onto the StripeCustomer, that fetches the customersExternalCustomerId from Orb, using the Stripe Customer ID as the externalCustomerId:

g.extend("StripeCustomer", (extend) => { extend.addField( "orbCustomer", g.ref("OrbCustomer").optional().join( "orb { customersExternalCustomerId(externalCustomerId: $id) }" )))) })

Once this is done, you can make a query to fetch this related data:

query FetchCustomers($email: String!) { stripe { customers(email: $email) { nodes { id name orbCustomer { balance timezone portalUrl } } } }

Which would return your linked data:

{ "data": { "stripe": { "customers": { "nodes": [ { "id": "1", "name": "Jane", "orbCustomer": { "balance": "1000000", "timezone": "America/Los_Angeles", "portalUrl": "" } } ] } } } }

Arguments of a joined field can be passed as inputs to the join query using the same variable syntax used for passing fields of the currrent object.

For example if you were joining on to a field with paging arguments those could be forwarded like so:

g.extend('Customer', extend => { extend.addField( 'contacts', g .ref('ContactConnection') .optional() .join( ` mongoDB { contactCollection( first: $first, after: $after, last: $last, before: $before, filter: { customerId: $customerId } ) } `, ) .arguments({ first:, after: g.string().optional(), last:, before: g.string().optional(), }), ) })

There are some limitations on joins at present:

  1. They can only pass in data from the current type, not any children of the current type.
  2. With most of our connectors, the fields that are required to perform a join must be present in the user's query.

We're working to eventually remove these limitations.

Was this page helpful?