Udgama Blog
Published in

Udgama Blog

GraphQL server with ExpressJS

New amazing query language for your API

Get exactly what you need

What is GraphQL?

As per the GraphQL documentation:

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.

GraphQL was started as an internal project at Facebook.

Why GraphQL?

  1. The bigger issue that it solves is Over-fetching and Under-fetching.
  2. It provides a single endpoint instead of multiple.
  3. It avoids multiple roundtrips to fetch related data.
  4. You can ask for what you need.
  5. You can get many API’s responses in a single request.
  6. Strongly typed language.

Let’s get started with creating our GraphQL server with ExpressJS.

Before starting, let’s look at what we are going to create:

GraphQL server running for an event query

Here, we are making a request for all the events, and we got all the events with only the data that we need.

How to get started?

Create your project folder and add dependencies:

mkdir graphql-server
yarn init -y
yarn add express express-graphql graphql mongoose

Now, we’ll create a server. For that let’s add the main file app.js

// app.js file
const express = require("express");const graphqlHttp = require('express-graphql');const mongoose = require('mongoose');const dotenv = require('dotenv');dotenv.config();
const app = express();
app.get('/', (req, res, next) => { res.send('<h1>Welcome to graphql server!</h1>');});
app.use('/graphql', graphqlHttp({ schema: // add schema, rootValue: // add resolver, graphiql: true,}));const user = process.env.ME;const pass = process.env.PASS;const db = process.env.DATABASE;const port = process.env.PORT;
mongoose.connect(`mongodb://${user}:${pass}@ds153730.mlab.com:53730/${db}`, { useNewUrlParser: true }).then(() => { console.log(`Server is running on port ${port}`); app.listen(port);}).catch(err => { console.log(err);});

Here, we are requiring all the dependencies.

express is for creating a new Express application and mongoose is for connecting to MongoDB database.

graphqlHTTP helps us by creating a graphQL server based on our schema.

With the graphiql attribute set to true, we are displaying a nice looking GraphiQL interface.

Now, we’ll define our schema.

We will define our schema in a schema.js file.

// schema.js file
const { buildSchema } = require('graphql');module.exports = buildSchema(` type Event { _id: ID! name: String createdAt: String creator: String } input EventInput { name: String createdAt: String creator: String } type RootQuery { events: [Event]! } type RootMutation { createEvent(eventInput: EventInput): Event! }
schema { query: RootQuery mutation: RootMutation }`);

Now we have our node Event, of type Event with fields as name, createdAt, creator and an autogenerated _id.

type RootQuery {    events: [Event]!}type RootMutation {    createEvent(eventInput: EventInput): Event!}

Here, We are adding query for events, which will return an array of type Event and a mutation createEvent will return an Event type data.

We use a query for all GET operations and mutation for POST, PUT and DELETE operations.

In mutation, we are passing arguments of input type EventInput.

schema {    query: RootQuery    mutation: RootMutation}

In the end, we are specifying our schema, what should we get from our server.

We are building our schema with the module buildSchema required from graphql.

Now our graphql server knows what we can ask for, but it does not know what it will respond with.

So, we have to add a resolver, which will resolve our queries.

Add a resolver file.

// resolvers.js file
const Event = require('./models/event');module.exports = { events: async () => { try { const events = await Event.find(); return events.map(event => { return { ...event._doc, _id: event.id, } }); } catch(err) { throw err; } }, createEvent: async (args) => { try { const existingEvent = await Event.findOne({ name: args.eventInput.name }); let newEvent; if (existingEvent){ throw new Error('Event already exists!'); } newEvent = await new Event({ name: args.eventInput.name, createdAt: args.eventInput.createdAt, creator: args.eventInput.creator
});
const result = await newEvent.save(); return { ...result._doc, }; }
catch(err){
throw err; } },}

Now our graphql server knows how to resolve the queries.

When we will request for all events, the server will resolve it by finding the events inside of our MongoDB database and return it.

And when we’ll request for mutation createEvent, it will add the event to the database.

Now, we’ll put everything together and update the app.js file.

// updated app.js
const express = require("express");const graphqlHttp = require('express-graphql');const mongoose = require('mongoose');const graphqlSchema = require('./schema');const graphqlResolvers = require('./resolvers');const dotenv = require('dotenv');dotenv.config();
const app = express();
app.get('/', (req, res, next) => { res.send('<h1>Welcome to graphql server!</h1>');});
app.use('/graphql', graphqlHttp({ schema: graphqlSchema, rootValue: graphqlResolvers, graphiql: true,}));const user = process.env.ME;const pass = process.env.PASS;const db = process.env.DATABASE;const port = process.env.PORT;mongoose.connect(`mongodb://${user}:${pass}@ds153730.mlab.com:53730/${db}`, { useNewUrlParser: true }).then(() => { console.log(`Server is running on port ${port}`); app.listen(port);}).catch(err => { console.log(err);});

Now it’s time to start our server.

node app.js
running mutation createEvent

Now, we have a nice looking GraphiQL interface for our backend.

You can get the complete code on GitHub.

Happy Coding 😊👍

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store