How to migrate from Mongoose to Prisma ORM
Introduction
This guide shows you how to migrate your application from Mongoose to Prisma ORM. We'll use an extended version of the Mongoose Express example as a sample project to demonstrate the migration steps.
You can learn how Prisma ORM compares to Mongoose on the Prisma ORM vs Mongoose page.
Prerequisites
Before starting this guide, make sure you have:
- A Mongoose project you want to migrate
- Node.js installed (version 18 or higher)
- MongoDB database
- Basic familiarity with Mongoose and Express.js
1. Prepare for migration
1.1. Understand the migration process
The steps for migrating from Mongoose to Prisma ORM are always the same, no matter what kind of application or API layer you're building:
- Install the Prisma CLI
- Introspect your database
- Install and generate Prisma Client
- Gradually replace your Mongoose queries with Prisma Client
These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses Mongoose for database access.
1.2. Set up Prisma configuration
Create a new Prisma schema file:
npx prisma init --datasource-provider mongodb
This command creates:
- A new directory called
prisma
that contains aschema.prisma
file; your Prisma schema specifies your database connection and models .env
: Adotenv
file at the root of your project (if it doesn't already exist), used to configure your database connection URL as an environment variable
The Prisma schema currently looks as follows:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
For an optimal development experience when working with Prisma ORM, refer to editor setup to learn about syntax highlighting, formatting, auto-completion, and many more cool features.
Update the DATABASE_URL
in the .env
file with your MongoDB connection string:
DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE"
2. Migrate the database schema
2.1. Introspect your database
MongoDB is a schemaless database. To incrementally adopt Prisma ORM in your project, ensure your database is populated with sample data. Prisma ORM introspects a MongoDB schema by sampling data stored and inferring the schema from the data in the database.
Run Prisma's introspection to create the Prisma schema from your existing database:
npx prisma db pull
This will create a schema.prisma
file with your database schema.
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
author String @db.ObjectId
categories String[] @db.ObjectId
content String
published Boolean
title String
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
}
2.2. Update relations
MongoDB doesn't support relations between different collections. However, you can create references between documents using the ObjectId
field type or from one document to many using an array of ObjectIds
in the collection. The reference will store id(s) of the related document(s). You can use the populate()
method that Mongoose provides to populate the reference with the data of the related document.
Update the 1-n relationship between posts
<-> users
as follows:
- Rename the existing
author
reference in theposts
model toauthorId
and add the@map("author")
attribute - Add the
author
relation field in theposts
model and it's@relation
attribute specifying thefields
andreferences
- Add the
posts
relation in theusers
model
Your schema should now look like this:
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
published Boolean
v Int @map("__v")
author String @db.ObjectId
author users @relation(fields: [authorId], references: [id])
authorId String @map("author") @db.ObjectId
categories String[] @db.ObjectId
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
posts posts[]
}
Then, update the m-n between posts
<-> categories
references as follows:
- Rename the
categories
field tocategoryIds
and map it using@map("categories")
in theposts
model - Add a new
categories
relation field in theposts
model - Add the
postIds
scalar list field in thecategories
model - Add the
posts
relation in thecategories
model - Add a relation scalar on both models
- Add the
@relation
attribute specifying thefields
andreferences
arguments on both sides
Your schema should now look like this:
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
posts posts[] @relation(fields: [postIds], references: [id])
postIds String[] @db.ObjectId
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
published Boolean
v Int @map("__v")
author users @relation(fields: [authorId], references: [id])
authorId String @map("author") @db.ObjectId
categories String[] @db.ObjectId
categories categories[] @relation(fields: [categoryIds], references: [id])
categoryIds String[] @map("categories") @db.ObjectId
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
posts posts[]
}
3. Update your application code
3.1. Install Prisma Client
Install the Prisma Client package:
npm install @prisma/client
After installing the Prisma Client package, generate Prisma Client:
npx prisma generate
3.2. Replace Mongoose queries
Start replacing your Mongoose queries with Prisma Client. Here's an example of how to convert some common queries:
- Mongoose
- Prisma Client
// Find one
const user = await User.findById(id);
// Create
const user = await User.create({
email: 'alice@prisma.io',
name: 'Alice'
});
// Update
await User.findByIdAndUpdate(id, {
name: 'New name'
});
// Delete
await User.findByIdAndDelete(id);
// Find one
const user = await prisma.user.findUnique({
where: { id }
});
// Create
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
name: 'Alice'
}
});
// Update
await prisma.user.update({
where: { id },
data: { name: 'New name' }
});
// Delete
await prisma.user.delete({
where: { id }
});
3.3. Update your controllers
Update your Express controllers to use Prisma Client. For example, here's how to update a user controller:
import { prisma } from '../client'
export class UserController {
async create(req: Request, res: Response) {
const { email, name } = req.body
const result = await prisma.user.create({
data: {
email,
name,
},
})
return res.json(result)
}
}
Next steps
Now that you've migrated to Prisma ORM, you can:
- Add more complex queries using Prisma's powerful query API
- Set up Prisma Studio for database management
- Implement database monitoring
- Add automated tests using Prisma's testing utilities
For more information and updates: