7. Interface and entity definitions
7m

Overview

Let's continue building our accounts subgraph! The accounts subgraph is responsible for all things user profile-related, and we listed out all of the types and fields we wanted to migrate over to this subgraph. In this list, we have the User interface and its corresponding implementing types (Host and Guest). That's where we'll start!

Tip: First time seeing GraphQL interfaces? Check out the Intermediate Schema Design side quest for more details on what they are and how they work.

In this lesson, we will:

  • Learn how to define an interface across multiple subgraphs
  • Review what an entity is and how to define entities
  • Review how to contribute fields to an entity

The User interface

Let's start with the User interface. We can find its definition in the monolith/schema.graphql file.

monolith/schema.graphql
"Represents an Airlock user's common properties"
interface User {
id: ID!
"The user's first and last name"
name: String!
"The user's profile photo URL"
profilePicture: String!
}

We know that the interface needs to exist in the accounts subgraph, since it's related to accounts and users. So let's go ahead and copy the definition, and paste it into the accounts subgraph schema.

subgraph-accounts/schema.graphql
"Represents an Airlock user's common properties"
interface User {
id: ID!
"The user's first and last name"
name: String!
"The user's profile photo URL"
profilePicture: String!
}

What about in the monolith subgraph? Well, we still need to keep the User interface defined there. We reference it as a return type for the Review.author field, and we also implement the interface for the Host and Guest types.

However, we don't need to keep all the extra fields that are the responsibility of the accounts subgraph! We can remove both name and profilePicture.

monolith/schema.graphql
"Represents an Airlock user's common properties"
interface User {
id: ID!
- "The user's first and last name"
- name: String!
- "The user's profile photo URL"
- profilePicture: String!
}

We do still need to keep the id field, because that's the bare minimum we need to identify a specific instance of a user. Like a stub, similar to when we reference an entity in Voyage I.

Make no mistake though! The User interface is not an entity. An interface is actually an example of a value type. Value types are types that are reused and shared across multiple subgraphs. These types can be object types, enums, unions, or interfaces (like our case!).

In Federation 2, interface definitions can be shared between subgraphs by default, and those definitions can differ in each subgraph. This is how we can remove the name and profilePicture fields from the User interface definition in the monolith subgraph!

Now that we're got our User interface squared away in both subgraphs, let's move on to the implementing types, Host and Guest.

Creating entities for Host and Guest

In the previous course (Voyage I), we talked about how entities are object types that can resolve their fields across multiple subgraphs. Let's review what else we learned about entities:

  • We can define entities in subgraphs, and these subgraphs can contribute fields to the entity and resolve these fields independently.
  • An entity can be referenced by using it as the return type for a field.

The Host and Guest types are perfect candidates for entities! They each have fields that different subgraphs can contribute to.

✏️ The Host entity

Let's first take a look at the Host type and its fields. For each field, we've added a comment on which subgraph should be responsible for that field, based on the separation of concerns principle.

monolith/schema.graphql
type Host implements User {
id: ID! # this will be the key field, a unique identifier for a particular instance of a Host
name: String! # accounts subgraph
profilePicture: String! # accounts subgraph
profileDescription: String! # accounts subgraph
overallRating: Float # reviews subgraph, eventually
}

Using the plan above, we'll need to do the following:

  • Define the Host type as an entity in both subgraphs, using the id field as the @key field.
  • Move three fields (name, profilePicture and profileDescription) over to the accounts subgraph, which will be responsible for contributing those fields to the Host entity.
  • The monolith subgraph will contribute the overallRating field (eventually, the reviews subgraph will, but let's take it one step at a time!).

Let's get to it!

Tip: Try using side-by-side windows for this process and throughout the course. We'll be splitting off types and fields from the monolith subgraph schema (on the left), and moving or duplicating them over to the accounts subgraph schema (on the right).

  1. In the accounts subgraph, let's create the Host type as an entity. Remember that it needs to implement the User interface.

    To make it an entity, we'll add the @key directive, with the id as its primary key.

    subgraph-accounts/schema.graphql
    type Host implements User @key(fields: "id") {
    id: ID!
    }
  2. From the monolith subgraph schema, let's move the three fields over to the accounts subgraph schema: name, profilePicture and profileDescription.

    subgraph-accounts/schema.graphql
    type Host implements User @key(fields: "id") {
    id: ID!
    "The user's first and last name"
    name: String!
    "The user's profile photo URL"
    profilePicture: String!
    "The host's profile bio description, will be shown in the listing"
    profileDescription: String!
    }

    We're moving these fields over, so don't forget to remove them from the monolith subgraph schema!

    monolith/schema.graphql
    type Host implements User {
    id: ID!
    - "The user's first and last name"
    - name: String!
    - "The user's profile photo URL"
    - profilePicture: String!
    - "The host's profile bio description, will be shown in the listing"
    - profileDescription: String!
    "The overall calculated rating for the host"
    overallRating: Float
    }
  3. Lastly, we'll need to define the Host type in the monolith subgraph schema as an entity as well.

    monolith/schema.graphql
    "A host is a type of Airlock user. They own listings."
    type Host implements User @key(fields: "id") {
    id: ID!
    "The overall calculated rating for the host"
    overallRating: Float
    }

That's it for the Host entity!

✏️ The Guest entity

Let's use the same process for the Guest entity, labelling each field with which subgraph should be responsible for it.

monolith/schema.graphql
"A guest is a type of Airlock user. They book places to stay."
type Guest implements User {
id: ID! # this will be the key field, a unique identifier for a particular instance of a Guest
name: String! # accounts subgraph
profilePicture: String! # accounts subgraph
funds: Float! # payments subgraph, eventually
}

We can see that it's very similar to what we did for the Host entity!

  • Define the Guest type as an entity in both subgraphs, using the id field as the @key field.
  • Move two fields (name and profilePicture) over to the accounts subgraph, which will be responsible for contributing those fields to the Guest entity.
  • The monolith subgraph will contribute the funds field (eventually, the payments subgraph will, but let's take it one step at a time!).

By the end of those steps, our subgraph schemas for the Guest entity should look like this:

subgraph-accounts/schema.graphql
"A guest is a type of Airlock user. They book places to stay."
type Guest implements User @key(fields: "id") {
id: ID!
"The user's first and last name"
name: String!
"The user's profile photo URL"
profilePicture: String!
}
monolith/schema.graphql
"A guest is a type of Airlock user. They book places to stay."
type Guest implements User @key(fields: "id") {
id: ID!
"Amount of money in the guest's wallet"
funds: Float!
}

Reviewing the schema plan

Going back to our schema plan, we can check off the User, Host and Guest types that we've added to the accounts subgraph!

Diagram of the types and fields that belong in the accounts subgraph. The types and fields for User, Host and Guest have been checked off to indicate that they are completed.

Practice

Which of the following statements are true about value types?

Key takeaways

  • Value types are types that are reused and shared across multiple subgraphs. Interfaces are an example of a value type.
  • Value type schema definitions can differ across subgraphs, in Federation 2.

Up next

Phew! We've seen value types in action, and made a bunch of changes to both of our schema files. In the next lesson, we'll publish our changes and test out our updated supergraph.

Previous
Next