Write GraphQL APIs on Node with MongoDB

June 25, 2018 0 Comments

Write GraphQL APIs on Node with MongoDB

 

 

In a REST API based app, the server defines the shape and size of the resource provided by an endpoint. So any request sent to a server will return a lot of data, sometimes more than desired.

GraphQL solves this problem by giving us the ability to define exactly what data we need from the server while also allowing us the freedom to request as much or as little data as you want.

In this post, you will learn how to set up your GraphQL server with Node and Express persisted by MongoDB. You will also see how to create mutations that can update and delete data, queries to load specific data. You will also see how to connect GraphQL with MongoDB using Mongoose.

Create a new directory in your system:

$ mkdir hero-gql
$ cd hero-gql

Inside, install a couple of developer dependencies:

$ yarn add babel-cli babel-preset-env babel-preset-es2015 babel-preset-stage-2 babel-register nodemon -D

Here, babel is used to transpile the ES6 code to ES5.

Now create a babel configuration file called .babelrc in the directory. Inside this file, write:

{"presets": ["env", "stage-2"]}

Inside the package.json file, write the scripts and main as given below:

{
"main": "src/app.js",
"scripts": {
"start": "nodemon src/app.js --exec babel-node --presets env,stage-2",
"build": "babel src -d dist --source-maps",
"serve": "node dist/app.js"
},
// leave everything else as it is
}

Express is a flexible Node framework that provides us with robust features for web app developement.

To create an Express server for your app, first install Express as a dependency in your system.

Now create a new folder called src with a file named app.js inside it. Write the following code inside it.

Run start script using NPM/Yarn on your command terminal and see your code work!

To create a GraphQL HTTP Server, we first need to install express-graphql, graphql, and graphql-tools as dependencies in our project.

$ yarn add express-graphql graphql-tools graphql

In the app.js file, import graphqlHTTP from the express-graphql package.

import graphqlHTTP from 'express-graphql';

Use the graphqlHTTP function inside the file like this:

const schema = {};
app.use('/graphql', graphqlHTTP({
graphiql: true,
schema
}));

Re-run the start script using NPM/Yarn, and go to localhost:3000/graphqlin your browser.

What you will get on your browser is called GraphiQL. It is a new tool created by Facebook to test GraphQL endpoints, queries, and mutations.

Don’t worry about the error in GraphiQL. We are getting it because we haven’t yet defined a valid schema object.

The schema is a model of the data that can be fetched using the GraphQL server. It defines the queries that a client can make in GraphQL, the types of data that can be fetched from the server, and the relationships that can exist between different types of data.

Currently in our app, we have set the schema as an empty object, which is not a valid thing to do.

Inside the src folder, and create a couple of files inside it.

Inside the schema.js file, write the following code:

I am importing the makeExecutableSchema from the graphql-tools package. We need to use this method to create the GraphQL schema. I am also importing the resolvers that will be created inside resolvers.js file.

Lets also define the typeDefs. This will contain a Query type that defines the name field as a String type.

Finally, we export the schema object with the help of makeExecutableSchema. The schema object takes in typeDefs and the resolvers.

Inside the resolvers.js file, create a resolvers object like this:

export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Rajat S';
},
},
};

The resolvers object takes in four arguments — root, args, context, and info. For now, the object returns a simple string.

We now need to hook this up with the app.js file. First, import the schemaobject into this file. Also remove the line const schema = {};.

import schema from './schema';

Re-run the start script using NPM/Yarn, and go to localhost:3000/graphqlin your browser.

For our GraphQL servers to respond to our queries, schema needs to have resolver functions for all fields. Resolver cannot be included inside the GraphQL schema, they must be added separately.

Inside schema.js file, define another field inside typeDefs.

const typeDefs = <br>  type Query {<br>    name: String!<br>    alias: String // new field<br>  }<br>

The difference between String! and String is that String returns null for an empty field. But String! will give you an error.

We now need to write a a resolver for the alias field. A resolver takes in four arguments:

  • root returns the result of the query from the parent value.
  • args takes in arguments.
  • context is used to share the same object with each resolver method.
  • info is used to get the information about the GraphQL.

Inside typeDefs, pass in an argument to alias like this:

const typeDefs = <br>  type Query {<br>    name: String!<br>    alias(heroName: String!): String!<br>  }<br>

Go to resolvers.js file, and write a resolver for alias:

export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Rajat S';
},
alias(root, {heroName}, context, info) {
return heroName;
}
},
};

Running a query for alias in the GraphiQL, you will get the output as:

The context can be used to provide some kind of authentication information. Inside the app.js file, add a context inside the app.use method.

app.use('/graphql', graphqlHTTP({
graphiql: true,
schema,
context: {
userId: 1
}
}));

To see if this works, log out the context inside the resolvers.js file:

export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Clark Kent';
},
alias (root, {heroName}, context, info) {
console.log (context);
return heroName;
},
},
};

Refresh the GraphiQL page, and you will get the {userId: 1} printed in the terminal.

Replace the context inside the console.log() with info. You will get this inside the terminal.

Queries in GraphQL are analogous to REST’s GET. Queries allow us to ask the server for the data we need. But unlike Rest, we can ask exactly what we need from the server.

Inside the schema.js file, re-write the typeDefs like this:

const typeDefs = <br>  type Hero {<br>    _id: ID<br>    name: String!<br>    alias: String!<br>  }<br>  type Query {<br>    allHero: [Hero]<br>  }<br>;

Here I have create a new type called Hero which has three fields:

  • _id with the field type of ID.
  • name with the field type of String!.
  • alias with the field type of String!.

I am then using this Hero type inside Query. Since I want my query to return an array, the Hero is wrapped inside a [].

That’s it. Hope this post helped you learn about about writing GraphQL APIs on Node.js with MongoDB, and feel free to share your feedback and ideas.


Tag cloud