Skip to content
Rudolf Olah
Rudolf Olah
  • Archives
  • About
Rudolf Olah

GraphQL with MongoDB using Mongoose and Node.js

Rudolf Olah, February 12, 2018May 12, 2020

As part of a prototype/exploratory project in March 2016, I explored how to build a GraphQL server using Node.js and interfacing with a MongoDB database using the Mongoose library.

The best reason to use GraphQL is if you have multiple frontend clients that communicate with your backend and they each have differing data needs.

For instance, if you have a mobile application and a website that communicate with the same backend API, they will need different data. The mobile app may want to make as few requests as possible on startup and batching the requests into one request is possible with GraphQL.

GraphQL Schema Example

import {
  GraphQLObjectType,
  GraphQLNonNull,
  GraphQLSchema,
  GraphQLString,
  GraphQLInt,
  GraphQLList,
  GraphQLID,
  GraphQLBoolean
} from 'graphql/type';
import co from 'co';
import mongoose from 'mongoose';

import models from './models';

var makeGQLString = function(desc) {
  return {
    type: GraphQLString,
    description: desc
  };
};

var makeNonNullGQLString = function(desc) {
  return {
    type: new GraphQLNonNull(GraphQLString),
    description: desc
  };
};

var makeGQLBoolean = function(desc) {
  return {
    type: GraphQLBoolean,
    description: desc
  };
};

var makeGQLInt = function(desc) {
  return {
    type: GraphQLInt,
    description: desc
  };
};

var listingType = new GraphQLObjectType({
  name: 'Listing',
  description: 'An event listing',
  fields: function() {
    return {
      id: makeNonNullGQLString('The id of the listing.'),
      slug: makeNonNullGQLString('slug'),
      title: makeGQLString('The title of the listing.'),
      description: makeGQLString('description'),
      description_html: makeGQLString('description_html'),
      category_id: GraphQLID,
      category_key: makeGQLString('category_key'),
      hashtag: makeGQLString('hashtag'),
      location: makeGQLString('location'),
      website: makeGQLString('website'),
      show_count: makeGQLInt('show count'),
      show_avatars_of_bookers: makeGQLBoolean('show_avatars_of_bookers'),
      show_tickets_sold_count: makeGQLBoolean('show_tickets_sold_count'),
      hide_date: makeGQLBoolean('hide_date'),
      capacity: makeGQLString('Capacity of the listing'),
      state: makeNonNullGQLString('State of the listing')
    };
  }
});

var eventType = new GraphQLObjectType({
  name: 'Event',
  description: 'An event',
  fields: function() {
    return {
      id: makeNonNullGQLString('Event id'),
      start_stamp: makeNonNullGQLString('Start of the event, timestamp'),
      end_stamp: makeNonNullGQLString('End of the event, timestamp'),
      city_name: makeGQLString('Event that the city is in')
    };
  }
});

var rootQueryType =  new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    listings: {
      type: new GraphQLList(listingType),
      resolve: function(parent, args, ast) {
        return models.Listing.find().limit(10);
      }
    },
    listing: {
      type: listingType,
      args: {
        id: {
          name: 'id',
          type: new GraphQLNonNull(GraphQLString)
        }
      },
      resolve: function(parent, args, ast) {
        return models.Listing.findOne({ _id: args.id });
      }
    },
    events: {
      type: new GraphQLList(eventType),
      args: {
        listing_id: {
          name: 'listing_id',
          type: new GraphQLNonNull(GraphQLString)
        }
      },
      resolve: function(parent, args, ast) {
        return models.Event.find({ listing_id: args.listing_id });
      }
    }
  }
});

var schema = new GraphQLSchema({
  query: rootQueryType
});

export var getProjection;
export default schema;

We declare a root query that contains certain fields that are resolved by particular functions. The type of each field can be a list, non-null or other types. The resolve function is what fetches data from the database (or whatever caching layer(s) you have).

Within the GraphQLObjectType we can define a structured object with more fields and define the types of those fields. This is in contrast to most REST APIs which provide no schema.

It’s also possible, as you define the fields, to provide descriptions of them. These descriptions can appear in a GraphQL API explorer and since they are built-in and supported as part of the GraphQL specification, the descriptions can be supported by multiple libraries. In contrast, most REST APIs do not place descriptions near the fields within the code; they provide the descriptions (if at all) within separate documentation.

When building this prototype to provide a GraphQL interface to a MongoDB database, it was very easy to declare the schemas for the models and then to provide them as part of the interface.

Web Development

Post navigation

Previous post
Next post

About this site

Rudolf Olah is an an experienced engineering leader passionate about empowering teams and driving growth through technology.

  • GitHub
  • LinkedIn
  • Twitter

Archives

  • March 2024
  • December 2023
  • May 2023
  • September 2022
  • January 2021
  • July 2020
  • May 2020
  • February 2020
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • April 2018
  • February 2018
  • November 2017
  • August 2016
  • June 2016
  • January 2014
  • June 2013
  • April 2009

Recent Posts

  • Buffers and Placeholders in Agile SCRUM Project Management
  • Engineering Management Tools: My Top Picks
  • Webpack and Frontend Build-Time Performance Engineering for React
  • Creating a Data Pipeline for Analytics, AI/ML, ChatGPT
  • Smart Contracts for Cosmos Blockchain
©2025 Rudolf Olah | WordPress Theme by SuperbThemes