# Type Safety with Prisma & MongoDB

Did you know that Prisma now supports MongoDB? In this article, we'll take a look at how to use Prisma to connect to MongoDB.

## What is Prisma?

Prisma is an open source ORM (Object Relational Mapper) for Node.js. It supports both JavaScript and TypeScript. It really shines when using TypeScript, helping you to write code that is both readable and type-safe.

> If you want to hear from Nikolas Burk and Matthew Meuller of Prisma, check out this episode of the MongoDB Podcast.
> 
> 

## Why Prisma?

Schemas help developers avoid data inconsistency issues over time. While you can define a schema at the database level within MongoDB, Prisma lets you define a schema at the application level. When using the Prisma Client, a developer gets the aid of auto-completing queries, since the Prisma Client is aware of the schema.

## Data modeling

Generally, data that is accessed together should be stored together in a MongoDB database. Prisma supports using embedded documents to keep data together.

However, there may be use cases where you'll need to store related data in separate collections. To do that in MongoDB, you can include one document’s `_id` field in another document. In this instance, Prisma can assist you in organizing this related data and maintaining referential integrity of the data.

## Prisma & MongoDB in action

We are going to take an existing example project from Prisma’s `prisma-examples` repository.

One of the examples is a blog content management platform. This example uses a SQLite database. We'll convert it to use MongoDB and then seed some dummy data.

If you want to see the final code, you can find it in the dedicated Github repository.

### MongoDB Atlas configuration

In this article, we’ll use a MongoDB Atlas cluster. To create a free account and your first forever-free cluster, follow the Get Started with Atlas guide.

### Prisma configuration

We'll first need to set up our environment variable to connect to our MongoDB Atlas database. I'll add my MongoDB Atlas connection string to a `.env` file.

Example:

```js
DATABASE_URL="mongodb+srv://:@.mongodb.net/prisma?retryWrites=true&w=majority"
```

> You can get your connection string from the Atlas dashboard.

Now, let's edit the `schema.prisma` file.

> If you are using Visual Studio Code, be sure to install the official Prisma VS Code extension to help with formatting and auto-completion.
> 
> While you’re in VS Code, also install the official MongoDB VS Code extension to monitor your database right inside VS Code!

In the `datasource db` object, we'll set the provider to "mongodb" and the url to our environment variable `DATABASE_URL`.

For the `User` model, we'll need to update the `id`. Instead of an `Int`, we'll use `String`. We'll set the default to `auto()`. Since MongoDB names the `id` field `_id`, we'll map the `id` field to `_id`. Lastly, we'll tell Prisma to use the data type of `ObjectId` for the `id` field.

We'll do the same for the `Post` model `id` field. We'll also change the `authorId` field to `String` and set the data type to `ObjectId`.

```js
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

model User {
  id    String  @id @default(auto()) @map("_id") @db.ObjectId
  email String  @unique
  name  String?
  posts Post]
}

model Post {
  id        String   @id @default(auto()) @map("_id") @db.ObjectId
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title     String
  content   String?
  published Boolean  @default(false)
  viewCount Int      @default(0)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  String   @db.ObjectId
}
```

This schema will result in a separate `User` and `Post` collection in MongoDB. Each post will have a reference to a user.

Now that we have our schema set up, let's install our dependencies and generate our schema.

```bash
npm install
npx prisma generate
```

> If you make any changes later to the schema, you'll need to run `npx prisma generate` again.

### Create and seed the MongoDB database

Next, we need to seed our database. The repo comes with a `prisma/seed.ts` file with some dummy data.

So, let's run the following command to seed our database:

```bash
npx prisma db seed
```

This also creates the `User` and `Post` collections that are defined in `prisma/schema.prisma`.

### Other updates to the example code

Because we made some changes to the `id` data type, we'll need to update some of the example code to reflect these changes.

The updates are in the [`pages/api/post/[id].ts` and `pages/api/publish/[id].ts` files.

Here's one example. We need to remove the `Number()` call from the reference to the `id` field since it is now a `String`.

```js
// BEFORE
async function handleGET(postId, res) {
  const post = await prisma.post.findUnique({
    where: { id: Number(postId) },
    include: { author: true },
  })
  res.json(post)
}

// AFTER
async function handleGET(postId, res) {
  const post = await prisma.post.findUnique({
    where: { id: postId },
    include: { author: true },
  })
  res.json(post)
}
```

### Awesome auto complete & IntelliSense

Notice in this file, when hovering over the `post` variable, VS Code knows that it is of type `Post`. If we just wanted a specific field from this, VS Code automatically knows which fields are included. No guessing!

### Run the app

Those are all of the updates needed. We can now run the app and we should see the seed data show up.

```bash
npm run dev
```

We can open the app in the browser at `http://localhost:3000/`.

From the main page, you can click on a post to see it. From there, you can delete the post.

We can go to the Drafts page to see any unpublished posts. When we click on any unpublished post, we can publish it or delete it.

The "Signup" button will allow us to add a new user to the database.

And, lastly, we can create a new post by clicking the "Create draft" button.

All of these actions are performed by the Prisma client using the API routes defined in our application.

Check out the `pages/api` folder to dive deeper into the API routes.

## Conclusion

Prisma makes dealing with schemas in MongoDB a breeze. It especially shines when using TypeScript by making your code readable and type-safe. It also helps to manage multiple collection relationships by aiding with referential integrity.

I can see the benefit of defining your schema at the application level and will be using Prisma to connect to MongoDB in the future.

Let me know what you think in the MongoDB community.