7. Interface and entity definitions
7m

Overview

Let's continue building our accounts ! The accounts is responsible for all things user profile-related, and we listed out all of the types and 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 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 s
  • Review what an is and how to define entities
  • Review how to contribute to an

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 , since it's related to accounts and users. So let's go ahead and copy the definition, and paste it into the accounts .

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 ? Well, we still need to keep the User interface defined there. We reference it as a return type for the Review.author , and we also implement the interface for the Host and Guest types.

However, we don't need to keep all the extra that are the responsibility of the accounts ! 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 , 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 in Voyage I.

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

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

Now that we've got our User interface squared away in both , 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 that can resolve their across multiple . Let's review what else we learned about entities:

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

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

✏️ The Host entity

Let's first take a look at the Host type and its . For each field, we've added a comment on which 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 in both , using the id as the @key .
  • Move three (name, profilePicture and profileDescription) over to the accounts , which will be responsible for contributing those to the Host .
  • The monolith will contribute the overallRating (eventually, the reviews 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 from the monolith (on the left), and moving or duplicating them over to the accounts (on the right).

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

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

    subgraph-accounts/schema.graphql
    type Host implements User @key(fields: "id") {
    id: ID!
    }
  2. From the monolith , let's move the three over to the accounts : 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 over, so don't forget to remove them from the monolith !

    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 as an 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 !

✏️ The Guest entity

Let's use the same process for the Guest , labeling each with which 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 !

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

By the end of those steps, our for the Guest 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 !

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 . Interfaces are an example of a value type.
  • Value type schema definitions can differ across , 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 .

Previous

Share your questions and comments about this lesson

Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.