Building A GraphQL API With Nodejs And MongoDB

Building A GraphQL API With Nodejs And MongoDB

In this tutorial, you’ll build and deploy a GraphQL server with Node.js that can query and mutate data from a MongoDB database that is running on Ubuntu 18.04.

While REST APIs are amongst the most popular when it comes to client consumption, they are not the only way to consume data and they aren’t always the best way. For example, having to deal with many endpoints or endpoints that return massive amounts of data that you don’t need are common. This is where GraphQL comes in.

With GraphQL you can query your API in the same sense that you would query a database. You write a query, define the data you want returned, and you get what you requested. Nothing more, nothing less. I actually had the opportunity to interview the co-creator of GraphQL on my podcast in an episode titled, GraphQL for API Development, and in that episode we discuss GraphQL at a high level.

You might remember that I wrote a tutorial titled, Getting Started with GraphQL Development Using Node.js which focused on mock data and no database. This time around we’re going to take a look at including MongoDB as our NoSQL data layer.

A few assumptions are going to be made going forward. I’m going to assume that you already have access to a MongoDB instance. If you don’t and need help getting MongoDB setup, you might check out my tutorial titled, Getting Started with MongoDB as a Docker Container Deployment. The other assumption is that you have Node.js installed and configured. While this tutorial will be a working example, if you want to get into more depth with GraphQL, I suggest you check out my eBook and video course titled Web Services for the JavaScript Developer.

Creating a New Node.js Project for GraphQL Development

The first step in this tutorial will be to create a new project with the dependencies and boilerplate GraphQL code. From the command line, execute the following commands:

npm init -y
npm install express express-graphql graphql mongoose --save

The above commands will create a new package.json file and install our dependencies. The backbone of this project will use Express.js, which is also commonly used for RESTful APIs. However, we’ll be processing GraphQL requests and connecting them to MongoDB with the Mongoose ODM.

The next step is to create an app.js file and include the following boilerplate JavaScript code:

const Express = require("express");
const ExpressGraphQL = require("express-graphql");
const Mongoose = require("mongoose");
const {
    GraphQLID,
    GraphQLString,
    GraphQLList,
    GraphQLNonNull,
    GraphQLObjectType,
    GraphQLSchema
} = require("graphql");

var app = Express();

Mongoose.connect("mongodb://localhost/thepolyglotdeveloper");

const PersonModel = Mongoose.model("person", {
firstname: String,
lastname: String
});

const PersonType = new GraphQLObjectType({
name: "Person",
fields: {
id: { type: GraphQLID },
firstname: { type: GraphQLString },
lastname: { type: GraphQLString }
}
});

const schema = new GraphQLSchema({});

app.use("/graphql", ExpressGraphQL({
schema: schema,
graphiql: true
}));

app.listen(3000, () => {
console.log("Listening at :3000...");
});

In the above code we are importing our dependencies, initializing Express.js, and connecting to our MongoDB instance with Mongoose. We’re planning to use a very simple Mongoose model which will also be seen in our GraphQL model.

Rather than reiterating the content that was discussed in the previous tutorial, we’re going to focus primarily on the schema in our project which will contain queries and mutations.

Designing GraphQL Queries for Retrieving MongoDB NoSQL Data

When it comes to our schema, there will be queries for retrieving data and mutations for creating, updating, or deleting data. We’re going to start by designing our queries which will retrieve data from MongoDB.

Take a look at the following queries:

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "Query",
fields: {
people: {
type: GraphQLList(PersonType),
resolve: (root, args, context, info) => {
return PersonModel.find().exec();
}
},
person: {
type: PersonType,
args: {
id: { type: GraphQLNonNull(GraphQLID) }
},
resolve: (root, args, context, info) => {
return PersonModel.findById(args.id).exec();
}
}
}
})
});

In the above code we have a people query as well as a person query. One will retrieve multiple documents and the other will retrieve a single document. When we wish to query for multiple documents, we specify we want to return a GraphQLList of the PersonType that we had created. This PersonType maps to our document model. We can simply do a find for all documents within our people MongoDB collection.

The person query is similar, but not quite the same. In the person query we accept an argument which must be present. With that argument we can use the findById function and return the result.

We didn’t need to specify the document properties because they are already conveniently mapped to our model because of our naming conventions. If we wanted to use different names, we could specify the properties in the find operation.

If we wanted to query for our data from a client facing application, we could run something like this:

{
people {
id,
firstname,
lastname
}
person(id: "123") {
firstname
}
}

You can try to run this query by navigating to http://localhost:3000/graphql in your web browser because we have GraphiQL enabled for troubleshooting.

Designing GraphQL Mutations for Creating, Changing, or Deleting MongoDB Documents

Now that we can query for documents, we probably want a way to create documents. Mutations are designed nearly the same as queries, but they are executed differently in the client facing application.

Within your schema we can modify it to the following:

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "Query",
fields: {
people: {
type: GraphQLList(PersonType),
resolve: (root, args, context, info) => {
return PersonModel.find().exec();
}
},
person: {
type: PersonType,
args: {
id: { type: GraphQLNonNull(GraphQLID) }
},
resolve: (root, args, context, info) => {
return PersonModel.findById(args.id).exec();
}
}
}
}),
mutation: new GraphQLObjectType({
name: "Mutation",
fields: {
person: {
type: PersonType,
args: {
firstname: { type: GraphQLNonNull(GraphQLString) },
lastname: { type: GraphQLNonNull(GraphQLString) }
},
resolve: (root, args, context, info) => {
var person = new PersonModel(args);
return person.save();
}
}
}
})
});

Notice that now we have a mutation and not just a query. For the mutation, we are requiring two arguments to exist and we are using them in the resolve function. Using the arguments, without further data validation, we create a new model instance and save it to the database. The results are returned to the client that executed the mutation.

To try this mutation, the following could be executed:

mutation CreatePerson($firstname: String!, $lastname: String!) {
person(firstname: $firstname, lastname: $lastname) {
id,
firstname,
lastname
}
}

The above code would make sense in GraphiQL. The variables would be populated with another part of the GraphiQL application. Various frameworks will have different expectations when it comes to executing mutations, but the same idea applies.

Conclusion

You just saw how to use MongoDB as the NoSQL database in your GraphQL web application. GraphQL can be used in combination with REST or as an alternative depending on your business needs. If you’d like to know how to create a RESTful application with MongoDB, you might want to check out my previous tutorial titled, Building a REST API with MongoDB, Mongoose, and Node.js.

This example was quite simple and a lot more can be accomplished with GraphQL.

Thanks For Visiting, Keep Visiting. If you liked this post, share it with all of your programming buddies!

How to set-up a powerful API with Nodejs, GraphQL, MongoDB, Hapi, and Swagger

Separating your frontend and backend has many advantages:

Separating your frontend and backend has many advantages:

  • The biggest reason why reusable APIs are popular — APIs allow you to consume data from a web client, mobile app, desktop app — any client really.
  • Separation of concerns. Long gone are the days where you have one monolithic-like app where everything is bundled together. Imagine you have an extremely convoluted application. Your only option is to hire extremely experienced/senior developers due to the natural complexity.

I’m all for hiring juniors and training your staff, and that’s exactly why you should separate concerns. With separation of concerns, you can reduce the complexity of your application by splitting responsibilities into “micro-services” where each team is specialized in their micro-service.

As mentioned above, the on-boarding/ramp-up process is much quicker thanks to splitting up responsibilities (backend team, frontend team, dev ops team, and so on)


Forward thinking and getting started

We will be building a very powerful, yet flexible, GraphQL API based on Nodejs with Swagger documentation powered by MongoDB.

The main backbone of our API will be Hapi.js. We will go over all the technology in substantial detail.

At the very end, we will have a very powerful GraphQL API with great documentation.

The cherry on top will be our integration with the client (React, Vue, Angular)


Prerequisites

  • NodeJS installed
  • Basic JavaScript
  • Terminal (any will do, preferably bash-based)
  • Text editor (any will do)
  • MongoDB (install instructions here) — Mac: brew install mongodb

Let’s goo!

Open the terminal and create the project. Inside the project directory we initialize a Node project.

Creating our project

Next, we want to setup our Hapi server, so let’s install the dependencies. You can either use Yarn or NPM.

yarn add hapi nodemon

Before we go on, let’s talk about what hapi.js is and what it can do for us.

hapi enables developers to focus on writing reusable application logic instead of spending time building infrastructure.

Instead of going with Express, we are going with Hapi. In a nutshell, Hapi is a Node framework. The reason why I chose Hapi is rather simple — simplicity and flexibility over boilerplate code_._

Hapi enables us to build our API in a very rapid manner.

Optional: check out this quick crash course on hapi.js:

The second dependency we installed was the good-ole nodemon. Nodemon restarts our server automatically whenever we make changes. It speeds up our development by a big factor.

Let’s open our project with a text editor. I chose Visual Studio Code.

Setting up a Hapi server is very straightforward. Create a index.js file at the root directory with the contents of the following:

  • We require the hapi dependency
  • Secondly, we make a constant called server which creates a new instance of our Hapi server — as the arguments, we pass an object with the port and host options.
  • Third and finally, we create an asynchronous expression called init. Inside the init method, we have another asynchronous method which starts the server. See server.start() — at the bottom we call the init()function.

If you’re unsure about async await — watch this:

Now, if we head over to [http://localhost:4000](http://localhost:4000) we should see the following:

Which is perfectly fine, since the Hapi server expects a route and a handler. More on that in a second.

Let’s quickly add the script to run our server with nodemon. Open package.json and edit the scripts section.

Now we can do the following 😎


Routing

Routing is very intuitive with Hapi. Let’s say you hit / — what would you expect to happen? There are three main components in play here.

  • What’s the path? — path
  • What’s the HTTP method? Is it a GET — POST or something else? — method
  • What will happen if that route is reached? — handler

Inside the init method we attached a new method to our server called route with options passed as our argument.

If we refresh our page we should see return value of our root handler

Well done, but there is so much more we can do!


Setting up our database

Right, next up we are going to setup our database. We’re going to use mongodb with mongoose.

Let’s face it, writing MongoDB validation, casting and business logic boilerplate is a drag. That’s why we wrote Mongoose.

The next final ingredient related to our database is mlab. Instead of running mongo on our local computer, we are gonna use a cloud provider like mlab.

The reason why I chose mlab is because of the free plan (useful for prototyping) and how simple it is to use. There are more alternatives out there, and I encourage you to explore all of them ❤

Head over to https://mlab.com/ and signup.

Let’s create our database.

And finally create a user for the database. That will be all we will be editing on mlab.


Connecting mongoose with mlab

Open index.js and add the following lines and credentials. We are basically just telling mongoose which database we want to connect. Make sure to use your credentials.

If you want to brush up your MongoDB skills, here’s a solid series.

If everything went according the plan, we should see ‘connected to database’ in the console.


Wohoo!

Good job! Take a quick break and grab some coffee, we are almost ready to dive into the “cool parts”.


Creating Models

With mongoDB, we follow the convention of models. In other words — data modeling.

It’s a relatively simple concept which you will be able to grasp. Basically we just declare our schema for collections. Think of collections as tables in an SQL database.

Let’s create a directory called models. Inside we will create a file Painting.js

Painting.js is our painting model. It will hold all data related to paintings. Here’s how it will look:

  • We require the mongoose dependency.
  • We declare our PaintingSchema by calling the mongoose schema constructor and passing in the options. Notice how it’s strongly typed: for example the name field can consist of a string, and techniques consists of an array of strings.
  • We export the model and name it Painting

Let’s fetch all of our paintings from the database

First we need to import the Painting model to index.js


Adding new routes

Ideally, we want to have URL endpoints reflecting our actions.

such as /api/v1/paintings — /api/v1/paintings/{id} — and so on.

Let’s start off with a GET and POST route. GET fetches all the paintings and POST adds a new painting.

Notice we modified the route to be an array of objects instead a single object. Also, arrow functions 😊

  • We created a GET for [/api/v1/paintings](http://localhost:4000/api/v1/paintings) path. Inside the handler we are calling the mongoose schema. Mongoose has built-in methods — the handy method we are using is find() which returns all paintings since we’re not passing in any conditions to find by. Therefore it returns all records.
  • We also created a POST for the same path. The reason for that is we’re following REST conventions. Let’s deconstruct (pun intended) the route handler — remember in our Painting schema we declared three fields: name — url — techniques 
  • Here we are just accepting those arguments from the request (we will be doing that with postman in a sec) and passing the request arguments to our mongoose schema. After we’re done passing arguments, we call the save() method on our new record, which saves it to the mlab database.

If we head over to [http://localhost:4000**/api/v1/paintings**](http://localhost:4000/api/v1/paintings) we should see an empty array.

Why empty? Well we haven’t added any paintings just yet. Let’s do that now!

Install postman, it’s available for all platforms.

After installation, open postman.

  • On the left you can see the method options. Change that to POST
  • Next to the POST method we have the URL. That’s the URL we want to send our method to.
  • On the right you can see blue button which sends the request.
  • Below the URL bar we have the options. Click on the body and fill in the fields like in the example.
{
  "name": "Mona Lisa",
  "url": "https://en.wikipedia.org/wiki/Mona_Lisa#/media/File:Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg",
  "techniques": ["Portrait"]
}

POST paintings

Alright. Good to go! Let’s open [http://localhost:4000/api/v1/paintings](http://localhost:4000/api/v1/paintings)

Excellent! We still have some way to go! Next up — GraphQL!


Here’s the source code just in case anyone needs it :-)


Building A REST API With MongoDB, Mongoose, And Node.js

Building A REST API With MongoDB, Mongoose, And Node.js

In this tutorial, we build A REST API With MongoDB, Mongoose, And Node.js .... Mongoose is Nodejs package for modeling Mongodb.

In this tutorial, we build A REST API With MongoDB, Mongoose, And Node.js .... Mongoose is Nodejs package for modeling Mongodb.

About a week or so ago I had written a tutorial titled, Getting Started with MongoDB as a Docker Container Deployment, which focused on the deployment of MongoDB. In that tutorial we saw how to interact with the MongoDB instance using the shell client, but what if we wanted to actually develop a web application with MongoDB as our NoSQL database?

In this tutorial we’re going to see how to develop a REST API with create, retrieve, update, and delete (CRUD) endpoints using Node.js and the very popular Mongoose object document modeler (ODM) to interact with MongoDB.

Before we get too invested in this tutorial, I wanted to point out that the focus of this tutorial won’t be around installing, configuring, or deploying MongoDB instances. I recommend you take a look at my previous tutorial if you need help with that. The assumption is that your MongoDB database is ready to go.

Configuring Node.js with Express Framework

To start things off, let’s go ahead and create a fresh Node.js project with the appropriate dependencies. From the command line, execute the following:

npm init -y
npm install express body-parser mongoose --save


The above commands will create a new package.json file and install Express.js, Mongoose, and a package that will allow us to pass JSON data around in our requests.

For simplicity, we’re going to keep all of our code within a single JavaScript file. Create an app.js file at the root of your project and include the following boilerplate code:

const Express = require("express");
const Mongoose = require("mongoose");
const BodyParser = require("body-parser");

var app = Express();

app.use(BodyParser.json());
app.use(BodyParser.urlencoded({ extended: true }));

app.post("/person", async (request, response) => {});
app.get("/people", async (request, response) => {});
app.get("/person/:id", async (request, response) => {});
app.put("/person/:id", async (request, response) => {});
app.delete("/person/:id", async (request, response) => {});

app.listen(3000, () => {
    console.log("Listening at :3000...");
});


In the above code we are doing a few things. First we are importing each of the dependencies that we had previously downloaded when creating our project. Next we are initializing Express Framework and configuring the body-parser package so we can receive JSON data in our payloads.

The API we develop will be create, retrieve, update, and delete (CRUD) oriented hence the five endpoint functions that are prepared. We’ll be adding the MongoDB and Mongoose logic to each of these endpoint functions.

Finally, we are listening for requests to our application on port 3000.

Interacting with MongoDB using the Mongoose ODM

With the foundation of our REST API in place, we can focus on the database logic. Within the project’s app.js file include the following near where you initialized Express Framework:

Mongoose.connect("mongodb://localhost/thepolyglotdeveloper");


The above line will connect to our MongoDB instance running on localhost and it will either use or create a thepolyglotdeveloper database. If you followed the Docker example, the database will have already been created. If you’re not using localhost, change it up as necessary.

After the connection information is in place, we can define our document models. This particular example will only have a single document model that looks like the following:

const PersonModel = Mongoose.model("person", {
    firstname: String,
    lastname: String
});


Our model is person which will create a people collection within our database. Each document in our collection will have the firstname and lastname properties. The model can be significantly more complex than what we have here.

So let’s take a look at each of our endpoints, starting with the creation of data:

app.post("/person", async (request, response) => {
    try {
        var person = new PersonModel(request.body);
        var result = await person.save();
        response.send(result);
    } catch (error) {
        response.status(500).send(error);
    }
});


When the client makes a POST request to our endpoint, we can use our PersonModel and the JSON payload provided to save into the database. Only the most basic of data validation is happening on our JSON payload and rather than using promises directly, we are using async and await, which in my opinion is a little cleaner. If the save is successful, we return the data back to the client facing application.

Now that we have data in our database, we can try to retrieve it:

app.get("/people", async (request, response) => {
    try {
        var result = await PersonModel.find().exec();
        response.send(result);
    } catch (error) {
        response.status(500).send(error);
    }
});


There are two different retrievals that can happen. We can retrieve everything, or we can retrieve something in particular. The first retrieval that we are looking at is the everything scenario. Using a find with no properties will get all data for a given collection, which in our scenario is the people collection. That data is then returned to the client facing application.

On the other side of things, we can try to retrieve a single document based on its stored id value:

app.get("/person/:id", async (request, response) => {
    try {
        var person = await PersonModel.findById(request.params.id).exec();
        response.send(person);
    } catch (error) {
        response.status(500).send(error);
    }
});


Given an id value defined by the client facing application, we can call the findById function rather than the find function. This function will find a single document based on the associated id. When we have this data we will return it back to the user.

Not bad so far, right?

Let’s finish this simple API with an update and a delete endpoint. Starting with an update, we can do the following:

app.put("/person/:id", async (request, response) => {
    try {
        var person = await PersonModel.findById(request.params.id).exec();
        person.set(request.body);
        var result = await person.save();
        response.send(result);
    } catch (error) {
        response.status(500).send(error);
    }
});


When the client provides an id value, we can first find the document by the id. Once we’ve found the document, we can set the properties that were provided in the request payload. Again, basic validation is performed. For example, if a property is provided that doesn’t appear in our model, it will be stripped out. In our model, none of the properties are required. This means whatever data appears in the payload, as long as it is valid, it will override what already exists. We can save any changes we made back to the database and return the data back to the client.

Our final endpoint for this example is the delete endpoint:

app.delete("/person/:id", async (request, response) => {
    try {
        var result = await PersonModel.deleteOne({ _id: request.params.id }).exec();
        response.send(result);
    } catch (error) {
        response.status(500).send(error);
    }
});


Again, we are expecting an id to be provided from the client facing application. When we have an id, we can use it in the deleteOne function and the document will be removed from the database.

If you run your application, you can play around with it using a tool like Postman or similar.

Conclusion

You just saw how to build a simple RESTful API using popular technologies such as Node.js, JavaScript, and MongoDB as the NoSQL database. If you’ve been following the blog, you might remember I did something similar in a tutorial titled, Developing a RESTful API with Node.js and MongoDB Atlas. With Atlas, we built a REST API, but it was with a cloud deployment of MongoDB.

If you’re interested in learning more about RESTful API development, I encourage you to check out my eBook and video course titled, Web Services for the JavaScript Developer, as it goes into significantly more depth.

A video version of this article can be found below.

How to setup a powerful API with GraphQL, Koa and MongoDB

How to setup a powerful API with GraphQL, Koa and MongoDB

Building API’s is super fun! Especially when you can leverage modern technologies such as Koa, GraphQL and MongoDB.

Building API’s is super fun! Especially when you can leverage modern technologies such as Koa, GraphQL and MongoDB.

Koa is a Node framework, just like Express is a Node framework. We’ll replace Express with Koa since Koa uses async/await syntax over callbacks.

Koa Github repository

Express Github repository

Getting started

The prerequisites for building our API are the following;

  • Node installed
  • Text Editor; I pick Visual Studio Code
  • Terminal
  • Browser

If you have everything you need, please proceed - if not, please install them.

Open your terminal and create a node project, like so;

So far we created our project folder, initialized a fresh Node project. Now we have the NPM packages available which we can use to install Koa, Mongo, and GraphQL.

Let’s install koa with NPM.

npm i koa

Starting a new Koa server is very simple. All we need is a server.js file and with the contents;

const Koa = require('koa');

const app = new Koa();

app.listen(9000);

app.on('error', err => {
  log.error('server error', err)
});

Starting the project with Node

GraphQL

We need two packages to setup GraphQL with Koa. koa-mount and koa-graphql.

npm i koa-mount koa-graphql

GraphQL requires we pass our initial schema to the GraphQL server. Let’s create one.

We will place the graphQL schema at graphql/schema.js

const { buildSchema } = require('graphql');

const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

module.exports = schema;

We pass our initial Query to the buildSchema function

Note: Notice how the argument for the buildSchema is a template literal. I encourage you take a look at this article if this is unfamiliar.

And now we can pass the initial schema to our graphql server.

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

Don’t forget to import koa-mount, koa-graphql, and finally the schema.js.

const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('./graphql/schema');

If we head over to localhost:9000/graphql;

Voila! Initial setup is done. It’s not very useful yet. Ideally, we would like to query GraphQL to save data to our mongodb and read from there.

Setting up MongoDB

In order to read and write with GraphQL, we need a place to read from. This is where Mongo will come in handy. We’ll save and read our data from there.

To make things simpler, we’re gonna use a cloud instance for Mongo. Head over to mlab.com and create a user and a mongo database.

Creating mongoDB

Once you created the database–you’ll need a user for the database.

Creating the MongoDB user

Now you can use the mongoDB paired with Mongoose. The remote url for your database will be;

mongodb://:@ds213615.mlab.com:13615/koa-graphql

Installing mongose

npm i mongoose

Creating database.js file

We create a dedicated file for databse connection.

const mongoose = require('mongoose');

const initDB = () => {

  mongoose.connect(
    'mongodb://indrek:[email protected]:13615/koa-graphql',
    { useNewUrlParser: true }
  );

  mongoose.connection.once('open', () => {
    console.log('connected to database');
  });

}

module.exports = initDB;

Note: Make sure you use the username and credentials for your database.

This block of code will try to connect to the remote mongodb. We need to call it somewhere now.

Open server.js and require and call the method.

const initDB = require('./database');

initDB();

If we did everything correct, our console should tell us we connected succesfully.

Bravo!

Notice how annoying it is to constantly refresh the server. Let’s solve this with a package called pm2

PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.

npm install pm2 -g

Add a script called start to our package.json

"scripts": {
  "start": "pm2 start server.js"
},

Very lovely for pm2 to run in the background, which frees up our terminal. If you ever want to stop the process, just run pm2 kill. Now we don’t have to restart our server all the time, pm2 does it automatically.

Note: pm2 logs returns the console log statements to the terminal.

MongoDB models

If you ever worked Mongo, you’re aware that mongoDB let’s us creates Models for our data. This is a neat way for us to structure how our data will look like.

Create a folder models and inside a file gadgets.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

/*
  notice there is no ID. That's because Mongoose will assign
  an ID by default to all schemas
*/

const GadgetSchema = new Schema({
  name: String,
  release_date: Date,
  by_company: String,
  price: Number,
});

module.exports = mongoose.model('Gadget', GadgetSchema);

Note: There is no ID field in our schema. That’s because Mongoose will assign

an ID by default to all schemas

Great. Let’s also add a collection and some dummy data. The collection name has to map our gadget name in plural. gadgets in this case.

After creating the collection, insert the document in JSON format like so;

That’s all for Mongo. Let’s fetch the data with GraphQL.

GraphQL Queries

GraphQL requires us to create types as well. Think of it like instructions for computers.

graphql/gadgetType.js

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLString } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({

  })
});

module.exports = GadgetType;

Notice we created a graphql type. Inside the fields we can specify the properties of the given type.

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLObjectType } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    release_date: { type: GraphQLString },
    by_company: { type: GraphQLString },
    price: { type: GraphQLString }
  })
});

module.exports = GadgetType;

Notice the GraphQLObjectType and GraphQLObjectType types we deconstruct from graphQL. These are the primitive types for graphQL.

Creating the graphQL types also grants type-hinting which we’ll use when creating our queries.

Last thing we need to do is refactor our schema.js. We want to query a gadget by id.

import the Gadget model,gadgetGraphQLType graphql type and GraphQLSchema, GraphQLObjectType, GraphQLString from graphQL to schema.js.

const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require('graphql');
const gadgetGraphQLType =  require('./gadgetType');
const Gadget = require('../models/gadget');

Next we need a root query. Every graphql query starts with curly brackets {} – this the root query.

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {

  }
})

Voila! Inside the fields we can specify the gadget query.

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(args.id)
      }
    }
  }
})

Notice the three properties inside the gadget query.

  • Node installed
  • Text Editor; I pick Visual Studio Code
  • Terminal
  • Browser

And finally export it.

module.exports = new GraphQLSchema({
  query: RootQuery
});

The file schema.js file should look like this;

const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require('graphql');
const gadgetGraphQLType =  require('./gadgetType');
const Gadget = require('../models/gadget');

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(args.id)
      }
    }
  }
})

module.exports = new GraphQLSchema({
  query: RootQuery
});

Now head over to http://localhost:9000/graphql and make the query.

{
	gadget(id: "5c4e188efb6fc05326ad9264") {
		name
    price
    by_company
    release_date
    id
  }
}

This it what we should end up with!

Thanks for reading! ❤ The source code can be found here.