GraphQL

Creating an API with GraphQL, MongoDB, and Express

GraphQL is a language built primarily for use with APIs. It interacts with Javascript and other languages quite easily. In this article, let's take a look at the basics around how to combine Express, MongoDB, and GraphQL into a basic API for getting titles and dates from a database.

GraphQL is a bit of a departure from classic REST APIs, but once you get used to it you'll see how easy it can be to run. Let's take a look.

Install GraphQL

The first step is to install the standard graphql packages and expresss on your Node.JS server by running the below installs on the command line:

shell Copy
npm i graphql npm i graphql-express npm i express npm i mongoose

A basic GraphQL Express Endpoint

Let's start with a functional express/GraphQL server. Create a file called index.js and insert this code:

javascript Copy
import express from 'express'; import { graphqlHTTP } from 'express-graphql'; import { buildSchema } from 'graphql' /* A schema is used to define how the data will look */ let schema = buildSchema(` type Query { title: String, age: Int, description: String } `); /* A root value is used to say what will be RETURNED for each schema element */ let root = { title: () => { return "Fjolt" }, age: () => { return 5 }, description: () => { return 'A website' } }; /* We tie it all together with express, so a user can access the endpoint */ let app = express(); app.get('/api', graphqlHTTP({ schema: schema, rootValue: root })); app.listen(4000);

As you can see, there are three main pieces required for GraphQL. First, we define a schema, which is the type of data our endpoint will return. Every GraphQL requires a 'type Query' schema, but after that you can use any name you want instead of 'Query'. You could have a type TeamMember schema, for example.

Next we have our root values. These are the items from the schema, and related functions which return a value for each. If a user then tries to get 'age' from the API, they will get a return of 5.

Finally, we return the data when the user does a GET request from /api. If you have Postman installed (which I would recommend for this tutorial), you can easily send a query with GraphQL like this to see how it works.

GraphQL has a very simple query language where we only need to send the keys of the elements we want in curly brackets. You can even do this at multiple levels for a multi-level object. An example is shown below:

Diagram of postman query

Schemas

GraphQL has a specific query language which allows us to create schemas. Schemas are essentially definitions for the type of data our API will return. A user could then send a query, to select specific components of that Schema.

Root Values

Root values are objects of all things in the schema.

Variables

It is also possible to add variables into the mix. To do that, we just need to define the variables in both the schema and the rootValue. We have to wrap our our variables in the rootValue in {} brackets.

javascript Copy
let schema = buildSchema(` type Query { title(firstName: String, lastName: String): String // ... } `); let root = { title: ({firstName, lastName}) => { return firstName + ' ' + lastName } // ... };

We can then query the title variable in Postman with the following query:

Diagram of postman query

Combining with MongoDB

Now we have a simple GraphQL interface, lets combine it with MongoDB. Create a file with your mongoDB schema. Mine is about articles, so it looks a little like what we've got below. Note, the schema here for the database is different, but that won't stop us:

javascript Copy
import mongoose from 'mongoose' const database = 'mongodb://localhost:27017/articles'; const connection = mongoose.createConnection(database, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false }); const schema = new mongoose.Schema({ title: 'String', description: 'String', articleText: 'String', date: 'Number' }); const Article = connection.model('Article', schema); export { Article };

Combine MongoDB

So first of all, add your new model to your index.js file, where you had your express router from before. Don't forget to connect to your mongoDB if you need to as well:

javascript Copy
// Import mongoose import mongoose from 'mongoose'; // Models import { Article } from './models/article.model.js'; // Connect to our mongoDB const database = 'mongodb://localhost:27017/database'; mongoose.connect(database, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });

Update our root and model

For this, I want to return all titles from my database and all page dates in separate arrays. First of all, let's update our schema to reflect that graphQL should return arrays of items:

javascript Copy
let schema = buildSchema(` type Query { title: [String] articleAge: [Int] } `);

Easy. Next, let's update our root variable. This time, we will connect to our mongoDB to return the articles, and compress them into one dimensional arrays:

javascript Copy
let root = { title: async () => { let allArticles = []; // Query our mongoDB let articles = await Article.find(); // Return data in appropriate format articles.forEach(function(item) { if(typeof item.title === "string") { allArticles.push(item.title); } }); return allArticles; }, articleAge: async () => { // Repeat let allDates = []; let articles = await Article.find(); articles.forEach(function(item) { if(typeof item.date === "number") { allDates.push(item.date); } }); return allDates; } };

Now we can run our API with the same query style as before, to get all our article dates and titles:

Diagram of postman query

Conclusion

That's all for today. If you're interested in learning more with us, follow us on twitter via @smpnjn to get the latest articles.

Here are some useful resources, and the code from today's final example.

Last Updated Wednesday, 21 April 2021