DEV Community

Praveen Durairaju
Praveen Durairaju

Posted on • Originally published at mongodb.com

How to Build a GraphQL API for MongoDB Using Hasura in Six Steps

In 2012, GraphQL was introduced as a developer-friendly API spec that allows clients to request exactly the data they need, making it efficient and fast. By reducing the need for multiple requests and limiting the over-fetching of data, GraphQL simplifies data retrieval, improving the developer experience. This leads to better applications by ensuring more efficient data loading and less bandwidth usage, particularly important for mobile or low-bandwidth environments.

Using GraphQL instead of REST on MongoDB is desirable for many use cases, especially when data from multiple MongoDB instances needs to be accessed simultaneously or when engineers need to join NoSQL data from MongoDB with data from another source.

However, engineers often encounter difficulties implementing GraphQL APIs and layering them onto their MongoDB data sources. This learning curve and the maintenance overhead often inhibit adoption. Hasura was designed to address this common challenge with adopting GraphQL.

Hasura is a low-code GraphQL API solution. With Hasura, even engineers unfamiliar with GraphQL can build feature-rich GraphQL APIs — complete with pagination, filtering, sorting, etc. — on MongoDB and dozens of other data sources in minutes.

Hasura also supports data federation, enabling developers to create a unified GraphQL API across different databases and services. In this guide, I’ll show you how to quickly connect Hasura to MongoDB and generate a secure, high-performance GraphQL API.

I will take you through the following steps to:

  • Create a project on Hasura Cloud
  • Create a database on MongoDB Atlas
  • Connect Hasura to MongoDB
  • Generate a high-performance GraphQL API instantly
  • Try out GraphQL queries with relationships
  • Analyze query execution

In addition, I will delve into the mechanics behind the generated API's exceptional performance, detailing the techniques and optimizations that contribute to its efficiency.

By the conclusion of this guide, you will possess the skills necessary to build your own high-performance, production-ready GraphQL API using Hasura, tailored for your existing or new MongoDB Atlas instance.

Step 1: Create a project on Hasura Cloud

Hasura Cloud Console

To begin, you will need a project on Hasura Cloud and a MongoDB database on Atlas. Head over to cloud.hasura.io to create an account or log in. Once you are on the Cloud Dashboard, navigate to Projects and click on New Project to create a new project.

Create a new project on Hasura Cloud

You can create a free project by selecting the region of your choice. In this example, we are using AWS infrastructure, US West region.

Remember the region selected. We want to co-locate the GraphQL API deployed using Hasura Cloud in the same region as the database on MongoDB Atlas. This will be done in one of the subsequent steps. Click on the Create Free Project button, as highlighted. As always, you can upgrade the project later as required.

Once the project is created, you’ll be taken to the project details page, which displays the GraphQL endpoint among other details. Take note of the Hasura Cloud IP on this page, as it’s required during the MongoDB Atlas setup to allow the connection from Hasura to MongoDB.

Launch Hasura Console

Click on Launch Console to open the project's Hasura Console. You will land on the API Explorer page to try out the GraphQL APIs.

Create free project

Click on the DATA tab at the top to navigate to the Data Management section of the console. Here you can connect to the various databases that Hasura supports. Choose MongoDB from the list and click on Connect Existing Database.

Connect Existing Database

At this point, Hasura requires the connection details of MongoDB.

Step 2: Create a database on MongoDB Atlas

Hasura can connect to a new or an existing MongoDB Atlas database and generate the GraphQL API for you. Now, go ahead and create a new database and use some autogenerated sample data.

Go to MongoDB Atlas, create a project if you don’t already have one, and navigate to the Database page under the Deployments section. You should see a page like the one below:

MongoDB deployment page

Click on the Build a Database button. On the next page, select the deployment specifics. Start with the Free M0 cluster, free forever and ideal for getting started. You can always upgrade later when required.

Deploy Mongo database

Give the cluster a name; for this example, use Hasura. You will need to select the region. For this tutorial, pick AWS as the provider and choose the us-west-2 region to keep the data close to the Hasura instance (recall that our Hasura cluster was deployed on US West, as well).

Provider AWS

Remember to choose the region closest to your users. Keeping your database and API region the same is recommended to avoid performance and latency issues.

Next, add your IP address for local connectivity and create a new database user with atlasAdmin permission that you’ll need to access the MongoDB cluster from Hasura Cloud.

Add IP Address

Note the password, as we will need it later. Now, click on Create Database User. Choose a connection method and skip the next steps. Optionally, in case you are stuck in any of the steps above, you can refer to the instructions for creating a new MongoDB database deployment in the docs, particularly until Step 4.

Step 3: Load sample dataset

Once the database deployment is complete, you might want to load some sample data for the cluster. You can do this by heading to the Database tab and under the newly created Cluster, click on the ... that opens an option to Load Sample Dataset. This may take a few seconds.

Load sample dataset

At this stage, we have created a Hasura Cloud project and a MongoDB Atlas database.

Step 4: Connect Hasura to MongoDB

To connect Hasura to MongoDB, first add the Hasura Cloud IP address to your MongoDB cluster. To do that, navigate to the Network Access page (under Security) from the Atlas dashboard.

Network Access MongoDB

Click on ADD IP ADDRESS and enter the Hasura Cloud IP that you obtained from the Hasura Cloud dashboard in the first step.

Add IP Address

Once completed, Hasura Cloud should be able to communicate with the MongoDB Atlas instance. The next step is to get the database connection string.

On the Atlas dashboard, head to the Database page and click on Connect next to the Hasura cluster created some steps back. Choose the Drivers option.

Connect to your Application MongoDB

You will get a popup with the connection string details. Copy the connection string for the database, which will be similar to this format:

mongodb+srv://praveen:<password>@hasura.1oyflxi.mongodb.net/?retryWrites=true&w=majority
Enter fullscreen mode Exit fullscreen mode

Note that you need to replace <password> with the actual password of the database user that you created earlier.

You can access the Database Users from the Database Access tab under the Security section of the left navigation menu. Remember that the database user needs to have atlasAdmin permission for the connection to work.

Now, move back to the Hasura Cloud dashboard for the next step.

As you are on the Connect Existing Database for MongoDB page, enter the values for the name of the database as mongodb, the connection string copied from the previous step. This instance comes with a sample database called sample_mflix. Enter that under the db config.

Connect MongoDB in Hasura

Finally, click on Connect Database and you are all set with the connection of Hasura and MongoDB, all hosted on their respective Cloud instances.

Step 5: Generate a high-performance GraphQL API

You can generate an API instantly for the sample database that was loaded to MongoDB by going to the mongodb -> Manage page on Hasura Console.

Track collections MongoDB

Review the collections from the sample database shown on this page. For example, you can see collections such as users, theaters, movies, comments, sessions, and embedded_movies. Now you can Track them to make sure Hasura generates the GraphQL (and REST) API for the collections.

Start by tracking the movies collection. Click on the Track button next to the movies collection.

In this step, you’ll need to indicate to Hasura the structure of the JSON object so that Hasura can inspect it and generate a GraphQL schema for it.

Insert the following JSON as input:

{
  "_id": {
    "$oid": "573a1390f29313caabcd42e8"
  },
  "plot": "A group of bandits stage a brazen train hold-up, only to find a determined posse hot on their heels.",
  "genres": [
    "Short",
    "Western"
  ],
  "runtime": {
    "$numberInt": "11"
  },
  "cast": [
    "A.C. Abadie",
    "Gilbert M. 'Broncho Billy' Anderson",
    "George Barnes",
    "Justus D. Barnes"
  ],
  "poster": "https://m.media-amazon.com/images/M/MV5BMTU3NjE5NzYtYTYyNS00MDVmLWIwYjgtMmYwYWIxZDYyNzU2XkEyXkFqcGdeQXVyNzQzNzQxNzI@._V1_SY1000_SX677_AL_.jpg",
  "title": "The Great Train Robbery",
  "fullplot": "Among the earliest existing films in American cinema - notable as the first film that presented a narrative story to tell - it depicts a group of cowboy outlaws who hold up a train and rob the passengers. They are then pursued by a Sheriff's posse. Several scenes have color included - all hand tinted.",
  "languages": [
    "English"
  ],
  "released": {
    "$date": {
      "$numberLong": "-2085523200000"
    }
  },
  "directors": [
    "Edwin S. Porter"
  ],
  "rated": "TV-G",
  "awards": {
    "wins": {
      "$numberInt": "1"
    },
    "nominations": {
      "$numberInt": "0"
    },
    "text": "1 win."
  },
  "lastupdated": "2015-08-13 00:27:59.177000000",
  "year": {
    "$numberInt": "1903"
  },
  "imdb": {
    "rating": {
      "$numberDouble": "7.4"
    },
    "votes": {
      "$numberInt": "9847"
    },
    "id": {
      "$numberInt": "439"
    }
  },
  "countries": [
    "USA"
  ],
  "type": "movie",
  "tomatoes": {
    "viewer": {
      "rating": {
        "$numberDouble": "3.7"
      },
      "numReviews": {
        "$numberInt": "2559"
      },
      "meter": {
        "$numberInt": "75"
      }
    },
    "fresh": {
      "$numberInt": "6"
    },
    "critic": {
      "rating": {
        "$numberDouble": "7.6"
      },
      "numReviews": {
        "$numberInt": "6"
      },
      "meter": {
        "$numberInt": "100"
      }
    },
    "rotten": {
      "$numberInt": "0"
    },
    "lastUpdated": {
      "$date": {
        "$numberLong": "1439061370000"
      }
    }
  },
  "num_mflix_comments": {
    "$numberInt": "0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, if you want to copy these objects from your Mongo collections directly, head to the Collections tab under the Database section.

Sample mflix database mongo

Click on the Validate button to validate the JSON document. In the next step, you will see the models derived from this document. Finally, click on the Track Collection button.

Track Collection

Step 6: Try out GraphQL queries

Once you track the collection, you should navigate to the API Explorer page on the Hasura Console to start trying out some GraphQL queries. Execute the following GraphQL query inside the GraphQL interface.

query {
  movies (limit: 10, order_by: { released: desc }) {
    _id
    title
    released
    imdb {
      rating {
        numberDouble
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

We are trying to fetch 10 movies, sorted by released, descending. You will get a JSON response on the right as you execute the query by clicking the play button.

GraphiQL query

And voilà! A GraphQL API for the movies collection is now tested and ready for consumption. Play around with different queries as you see them on the Explorer tab on the left sidebar. You can repeat this for tracking more collections like comments, users, theaters, etc., and get APIs generated for all of them.

How is the GraphQL API highly performant?

Hasura's instant generation of the GraphQL API for collections significantly minimizes the need for boilerplate code, which would otherwise be required in the form of GraphQL resolvers on any server.

Ensuring that both the database and the API reside in the same region mitigates latency concerns. However, let's delve deeper into the mechanics of query execution behind the scenes. It essentially revolves around these key factors:

1: Database pushdown with query optimization

Hasura operates as a compiler that receives a GraphQL query, enriches it with predicates as part of the query, and then delegates the query with projection, relationships, and authorization rules to the database to handle the workload. This approach circumvents server-side data processing and capitalizes on the database's capabilities to achieve high efficiency and performance.

Given GraphQL's inherent capability for clients to specify their desired data, it becomes imperative to retrieve only the exact fields requested by the client. Hasura achieves this by compiling the query with projection. In the absence of Hasura, a typical query might be suboptimal, resulting in fetching unnecessary data (more data than required).

Database pushdown with query optimization

2: Usage of aggregation pipelines

Let’s analyze the query that is generated by Hasura. For the example, GraphQL query that we used above, click on the Analyze button on the GraphiQL section of the API Explorer page.

You’ll see that the query execution plan looks like this:

{
  "aggregate": "movies",
  "pipeline": [
    {
      "$sort": {
        "released": -1
      }
    },
    {
      "$limit": 10
    },
    {
      "$replaceWith": {
        "released": {
          "$dateToString": {
            "date": "$released"
          }
        },
        "_id": "$_id",
        "imdb": {
          "$cond": {
            "if": "$imdb",
            "then": {
              "rating": {
                "$cond": {
                  "if": "$imdb.rating",
                  "then": {
                    "numberDouble": "$imdb.rating.numberDouble"
                  },
                  "else": null
                }
              }
            },
            "else": null
          }
        },
        "title": "$title"
      }
    }
  ],
  "cursor": {}
}
Enter fullscreen mode Exit fullscreen mode

You can see the usage of aggregation pipelines for high performance.
Iterating on the API with updates to collections
Updating the structure of a document in a collection is a straightforward process with Hasura. Simply adjust the Hasura metadata to include or exclude the modified fields. The schema's flexibility allows you to update the logical model to incorporate API changes seamlessly. No database migrations are necessary; — just add or remove fields from the metadata to reflect in the API.

Summary

The integration of MongoDB with Hasura's GraphQL Engine introduces a heightened level of efficiency and scalability for developers. Harnessing Hasura's ability to create a unified GraphQL API from varied data sources, developers can swiftly expose MongoDB data through a secure, high-performance, and extensively customizable GraphQL API.

Resources to learn more about the integration.

Top comments (0)