Praveen Durairaju
Posted on June 25, 2024
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
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.
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.
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.
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
.
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:
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.
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).
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.
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.
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.
Click on ADD IP ADDRESS
and enter the Hasura Cloud IP
that you obtained from the Hasura Cloud dashboard in the first step.
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.
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
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.
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.
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"
}
}
Alternatively, if you want to copy these objects from your Mongo collections directly, head to the Collections tab under the Database section.
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.
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
}
}
}
}
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.
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).
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": {}
}
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.
Posted on June 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.