Skip to content

Integrating MongoDB as a Datasource to Apollo GraphQL

In this blog post, we will explore how to integrate MongoDB as a datasource to an Apollo GraphQL server using TypeScript. We assume you have already set up the required environment variables for MongoDB connection.

Step 1: Install Dependencies

In your project directory, open the terminal and run the following command to install the required packages:

npm install @apollo/server mongodb apollo-mongodb-datasource jsonwebtoken

Configuring MongoDB Connection

The code provided already has the MongoDB connection configuration. We are using the MongoClient from the mongodb package to connect to the MongoDB cluster.

import { MongoClient } from "mongodb";
import jwt from "jsonwebtoken";

const clusterUrl = process.env.MONGO_CLUSTER_URL;
const username = encodeURIComponent(process.env.MONGO_USER as string);
const password = encodeURIComponent(process.env.MONGO_PASS as string);
const authMechanism = "DEFAULT";
const mongoUri = `mongodb+srv://${username}:${password}@${clusterUrl}/?authMechanism=${authMechanism}`;

const client = new MongoClient(mongoUri);

client.connect().catch(console.error);

Defining the ApolloContext

Next, let’s define the ApolloContext interface to include the MongoDB data source we will use in our resolvers:

import { BaseContext } from "@apollo/server";
import jwt from "jsonwebtoken";

export interface ApolloContext extends BaseContext {
  authorization?: string;
  jwt?: jwt.JwtPayload | null | string;
  dataSources: {
    listings: Listings;
  };
}

Creating the MongoDB Data Source

Now, let’s create a MongoDB data source called Listings that extends MongoDataSource from the apollo-mongodb-datasource package. This data source will interact with the listings collection in the amazon database.

import MongoDataSource from "apollo-mongodb-datasource";

export class Listings extends MongoDataSource {
  getListings = async (uuid: string, asin: string) =>
    await this.find({
      "product.asin": asin,
      "user.uuid": uuid,
    });
}

Integrating MongoDB Data Source

In the code provided, the MongoDB data source has already been integrated into the Apollo server context.

import { ApolloServer } from "@apollo/server";
import { Listings } from "./path/to/Listings"; // Replace with the correct path

const server = new ApolloServer({
  resolvers,
  typeDefs,
  introspection: true,
  plugins: [authenticationMiddleware(["LoginMutation", "Login"])],
});

export default startServerAndCreateNextHandler(server, {
  context: async (req, res) => ({
    req,
    res,
    authorization: req?.headers?.authorization,
    jwt: decode(req?.headers?.authorization),
    dataSources: {
      listings: new Listings(client.db("amazon").collection("listings")),
    },
  }),
});

In the context function, we instantiate the Listings data source and pass the MongoDB database collection listings to the data source constructor.

Implementing Resolvers

Finally, let’s integrate the provided resolver code with our Apollo server and connect it to the MongoDB data source.

import { ApolloContext } from "@/pages/api/graphql";
import { ApolloError } from "apollo-server";
import type { Document } from "mongodb";

export async function getListings(
  _: unknown,
  input: { asin: string },
  { dataSources: { listings }, jwt }: ApolloContext
): Promise<Document[] | ApolloError> {
  try {
    return await listings?.getListings(
      (jwt as { uuid: string })?.uuid,
      input.asin
    );
  } catch (error) {
    return new ApolloError("error in getListing resolver");
  }
}

export const resolvers = {
  Query: {
    getListings,
    //...
  },
  //...
};

By adding the getListings resolver to the Query object, we’ve integrated our resolver with the Apollo server. The resolver uses the Listings data source to fetch data from MongoDB based on the input parameters (asin) and the user’s JWT (jwt). If an error occurs during the process, an ApolloError is thrown to handle the error gracefully.

Conclusion

Now, your GraphQL server can interact with MongoDB to provide data to your clients seamlessly.

Happy hacking 🚀