Creating a GraphQL API with Apollo, Node, Express, Sequelize, and Postgres.
TL;DR - https://github.com/andrecalvo/GraphQL-Apollo-Node-Express-Apollo-Postgres-Sequelize-starter
I recently started a project where I wanted to use Apollo GraphQL and Node/Express to create an api. Although the individual documentation for these libs are great, when trying to use them together I looked to blogs for help.
There were a handful of articles to read (some of which helped me create this) but I struggled to find a “simple” example with minimal dependencies and workarounds.
It’s probably worth pointing out now that the intention of this article is to briefly explain some of the code to let you dig around the repo yourself.
This project uses the following:
- Postgres
- Node with an Express server
- Apollo GraphQL
- Sequelize
The models and data
If you follow the readme you should end up with a data set with 3 categories and 3 locations (this is generated via the migrations and seeds, you can find out more about this here).
There is a many-to-many relationship between tables. For example, a location can have many categories and vice versa. You can see how this is achieved with Sequelize in the models
directory.
"use strict";
module.exports = (sequelize, DataTypes) => {
var Categories = sequelize.define("Categories", {
name: DataTypes.STRING,
updatedAt: DataTypes.INTEGER,
createdAt: DataTypes.INTEGER,
id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true
}
});
Categories.associate = function(models) {
Categories.belongsToMany(models.Locations, {
through: "CategoriesLocations",
foreignKey: "categoryId"
});
};
return Categories;
};
Here’s the example categories
model. As well as the basics of setting the property data types you can also see that we set the association using the name of the join table and foreign key. As this is a many-to-many relationship so we have a similar association in the locations
model. Sequelize has various different features so I suggest looking at their documentation if you have a different use case.
Resolvers
Creating an Apollo server requires you to pass in resolvers. Resolvers essentially hold the logic of how your queries/mutations map to the appropriate data.
In the case of this project we have a categories
resolver which uses Sequelize to query the database and return all of the categories.
categories: (parent, args, { db }, info) => {
return db.Categories.findAll();
}
The rest of the resolvers can be found in the resolvers
directory. There is a more complicated example for locations which shows how you can pass arguments from your query.
Queries/Mutations
After running your server you should be able to access the GraphQL playground on http://localhost:4000/graphql.
The api exposes a few simple queries. You can list all the categories and the locations. You can also pass in an argument to the locations query and only show locations based on their ID.
To find them all just take out the argument `(categoryId:1)`
query {
locations(categoryId:1){
name,
id
}
}
To find all categories:
query {
categories{
name,
id
}
}
There is also a mutation which allows you to add a category.
mutation {
addCategory(categoryName: "Night life") {
name
}
}
The schema
directory contains all the code for this. I followed a great article which showed a nice way modularise your types, queries and mutations.
There is more to look at in this project but hopefully it’s brief and vanilla enough to be self-explanatory. Feel free to get in contact if you have any questions.