Today, I want to show you how to build serverless backends with the Hasura GraphQL API. After looking at GraphQL and its advantages, we will learn how to create new tables for our API. Next, we want to fill our database with real data. Of course, we want to have relationships between our tables. Finally, we will learn how to manipulate the data using mutations. No previous knowledge of GraphQL is required to follow this tutorial.
Table of Contents
- About GraphQL
- About Hasura
- Creating a project
- Create tables
- Insert data
- Object relationship
- Array relationship
- Many-to-many relationship
- Join the community
GraphQL is a typed query language for APIs. More and more tech companies, including tech giants like Facebook, Twitter and GitHub, are switching from common REST apis to GraphQL solutions. The main advantages of GraphQL over other API architectures like REST are:
- Get the exact data you need with easily understandable queries
- Get reliable results and helpful error messages
- Fast and lightweight applications because the data is accessed directly instead of through a server
- Get several resources with one query without using several URLs and chaining resources
- Use one endpoint for all data and typed fields for correct data access
- Add GraphQL easily to your existing applications
Here is a sample query:
And its corresponding result:
As you can see, the query is very intuitive and the result is predictable. You get exactly what you ask for: not more and not less.
As web applications tend to get more complex, there is a growing need for fast and easily maintainable solutions. So this is probably a good time to have a glimpse at GraphQL. But how do we use it? Do I need to build my own server? How can we connect it to our frontend? Don’t worry, we’ll get there.
Hasura provides you with an open source GraphQL engine that runs in a Docker container. Hasura connects to the Postgres database that is created with the project. You can also run Hasura GraphQL on top of an existing project. This can in particular be useful if you want to migrate to GraphQL, as it allows you to do the migration in smaller steps.
There are several options as to where you can deploy your GraphQL API: Heroku, Docker, Digital Ocean, Azure, AWS and Google Cloud.
Creating a project
In this post, we will get started with Heroku. We are going to create a Harry Potter api 🤓
On the dashboard, choose a (unique) name for your api and click the “Deploy” button:
That was easy, right? Now, if you scroll to the bottom you will see this:
When you click on “View”, the Hasura console will open in the GraphiQL tool, which is also one of the features that makes your life with GraphQL super easy. In the Hasura console, you can create tables and test queries. Let’s have a quick look at the console:
- This is the (only) endpoint used to interact with the api. When we later poll data from external services, this is the URL we need to access. And yes, you’ve seen correctly: requests to GraphQL are always POST requests.
- Here, you can add request headers. If you want to add authentication (e.g. with JWT tokens) later, you can add the headers here.
- This is the field where you can test queries.
- Here, the results will be displayed.
- We will go there next, to create our first table.
We first want to create a table to store movies. Let’s do that!
- Name of the table.
- It is recommended to add an ID to all tables. You can use an Integer or UUID. We’ll use UUID. Because we don’t want to pass an ID every time we create an object, Hasura offers a method to create it automatically.
- Adding more fields.
- We need to define the primary key for each table. This will be our ID.
Create the following two tables:
characters (id: UUID, name: Text, hair_color: Text, house: Text, wizard: Boolean, birth_year: Integer, patronus: Text)
actors (id: UUID, name: Text, birth_year: Integer, awards: Integer)
Let’s add some data data:
Add one other character, as well as two movies and two actors.
Now that we have some data, we can make our first query in GraphiQL.
It will return the two characters that we have already inserted into our characters table.
There are a lot of different constraints you can add to your queries. For example, you can make sure only to get a certain number of objects. Or only get the objects where a certain condition is true. All this is very well documented by Hasura: https://docs.hasura.io/1.0/graphql/manual/queries/simple-object-queries.html. You can read through it and tweak your queries, so that they return different results. You might have to add some more data in order to do so.
Currently, we have three tables that are all independent from each other. With a query, we can retrieve movies, characters and actors. But we cannot retrieve the movies with their characters and in turn the respective actors. In order to do this, we need to define relationships.
There are two different types of relationships: the object relationship and the array relationship. The object relationship is a one-to-one relationship. For example, a character has a single nested resource that is called actor. The array relationship is a one-to-many relationship. For example, a movie will have an array of nested resources called scenes.
Let’s first model the relationship between characters and actors. The first step is to add a actor_id to the characters table:
After adding the column, we need to edit it and to make sure that the actor_id is actually a foreign key, pointing to the actors table.
When we go to the tab “Relationships” on characters, a suggested relationship will appear. That’s right — Hasura detects foreign keys automatically and makes suggestions regarding relationships. As a name, we’ll take “actor”.
Next, we want to connect the characters with the corresponding actors in our database. When we now look into the characters table, we can see that the actor_id for the previously created characters is NULL. We can now edit the data and add the ids of the actors that correspond to these characters.
Now the characters and their actors are linked. Now we can access fields from the actors along with the characters in the same query:
The array relationship is a one-to-many relationship. This means that one object of a table can have several objects of another table. Let’s say in our example, one movie can have several scenes and each scene belongs to one movie. A scene has an id, a name, a location and a movie_id. So let’s create a new table called “scenes” to our database:
Great! Now, just like we did before, we need to modify the table and make the movie_id a foreign key:
When we now go to the movies table and click on “Relationships”, we can see the suggested array relationship for scenes. Let’s add this relationship and call it “scenes”. This is all that is necessary to create an array relationship. To test it, insert some rows into the scenes table.
As explained before, the array relationship is a one-to-many relationship. However, in our case of movies and characters, we have a many-to-many relationship. One movie can have several characters and one character can appear in several movies. For this scenario, we need to create a join table that we will call “movie_characters” in which we can store the relationship between one movie and one character. Let’s create the “movie_characters” table that has an ID, a movie_id and a character_id.
From the perspective of the movie_characters table, we need object relationships to both the movies table and the characters table. This is because in each movie_character, there is one movie and one character stored.
Like above, edit both the movie_id and the character_id on the movie_character table and tick the checkbox for them to be foreign keys. Then add the correct reference table and the reference column. For the movie_id, the reference table is movies and for the character_id, the reference table is characters. For both reference columns, it will be ID.
When you now click the tab “Relationships”, you’ll see two suggestions for object relationships. Add them both and call them “movie” and “character”. Once added, it should look like this:
Of course, like above, we need to create the relationships with our data. Create new rows in the movie_characters table for each movie — character relationship, using their IDs.
Yayy, now all our tables are modelled with their correct relationships. Let’s test it with a query.
Isn’t this neat? With just one query, we are able to access several resources with those fields we want. Compared to REST where usually the whole object is returned, we can reduce the query to the essentials. This makes the API more efficient, more lightweight and easier to handle.
So far, we learned how to get data from our API. But what about adding new data? In our case, we might want to add a movie or a character. For this, we need mutations. Mutations are easy to use with the GraphQL API and just like queries, we can try them in the Hasura console:
Let me explain what is happening here. Inside a mutation, we can call different methods like insert, update or delete on the resources that we store in our database. In our case, we want to insert a new movie. We need to pass the movies as objects and it is possible to insert several objects in one mutation. In the end, we need to return something, which is the ID of the newly created object in our example.
Again, there is full documentation on mutations on the Hasura website: https://docs.hasura.io/1.0/graphql/manual/mutations/index.html. Go through the examples and try some other mutations, like deleting a movie.
That is it for now. I hope you had fun learning about GraphQL and that you are eager to extend your Harry Potter API with lots of new tables and data. If something is not clear, you can always send me an email at firstname.lastname@example.org or message me over Twitter: https://twitter.com/rubydwarf.
Stay tuned for updates. I will soon publish another blogpost on how to connect your Hasura backend to your VueJS frontend 🎉
Join the community
Hasura is being used by a growing number of developers. Join the friendly community and keep up with updates.
If you want to start building your own projects with Hasura, you can join their discord channel here: https://discordapp.com/invite/hasura. There is already a pretty large community and you will get help very quickly.
🐦 Twitter: https://twitter.com/hasurahq
⭐️ Github: https://github.com/hasura/graphql-engine