How to Migrate from Sequelize to Prisma
Sequelize was good, but now we know: Prisma is better. No need to manually create model files as all of that is done for us via a prisma.schema
file. That's all I needed to switch, your reasons may be different, but nonetheless, we're in the same predicament: How do we migrate our app from Sequelize to Prisma?
LET ME SHOW YA.
Count
This method counts the number of rows in a particular database table. Sequelize did things right here. Both libraries use .count()
, the only difference is what variable name you store your models in.
Sequelize:
const userCount = await models.Users.count()
Prisma:
const userCount = await prisma.Users.count()
Find All
A small syntax difference here as Sequelize uses .findAll()
and Prisma uses .findMany()
.
Sequelize:
const channels = await models.Channels.findAll()
Prisma:
const userCount = await prisma.Channels.findMany()
Find One
Here, Sequelize uses .findOne()
while Prisma uses .findUnique()
. It's important to note, when using Prisma's version, .findUnique()
requires that the property you use to search has an @id
or @unique
attribute defined in your schema. If not, the method will throw an error. If looking for a row via a non-unique property, it's advisable to use Prisma's .findFirst()
method instead.
Sequelize:
const thread = await models.Threads.findOne({
where: {
id: req.params.id
}
})
Prisma:
// can only query by `id` or `slug` since only those two have an
// @id or @unique property listed in the model definition
// querying by `title` would not work here
const thread = await models.Threads.findUnique({
where: {
id: req.params.id
}
})
// if querying by a non-unique property, use findFirst instead
const thread = await models.Threads.findFirst({
where: {
title: req.body.title
}
})
model Threads {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
slug String @unique @db.VarChar(255)
}
Include
For includes, Sequelize uses an array of objects and requires you reference a model object directly.
Prisma cleans things up a bit by using simplistic object syntax where you set a property equal to true
if you want to include it on your call. This property must be set within your table's schema in prisma.schema
, if not, Prisma will not process the query correctly. I've provided an example down below on what your schema should look like for the example query to work. If you'd like to understand relations better, check out the prisma docs here.
Sequelize:
const thread = await models.Threads.findOne({
where: {
id: req.params.id
},
include: [{ model: models.Channels }]
})
Prisma:
const thread = await models.Threads.findUnique({
where: {
id: req.params.id
},
include: {
channel: true
}
})
model Threads {
id Int @id @default(autoincrement())
channelId Int
title String @db.VarChar(255)
slug String @unique @db.VarChar(255)
channel Channels? @relation(fields: [channelId], references: [id])
}
Update
Sequelize uses two arguments in its update call: the first is what properties you want to update, the second is a where clause that determines what row you want to update.
Prisma differs in that it uses only one argument, but specifies what data you'd like to update inside a data
property.
I prefer Prisma's syntax here since you don't need to memorize the position of arguments like you do for sequelize (eg. what comes first, the where clause or the data object?).
Sequelize:
await models.Thread.update(
{
title: 'Sequelize to Prisma Guide'
},
{
where: {
id: req.params.id
}
}
)
Prisma:
const updateUser = await prisma.Threads.update({
where: {
id: req.params.id
},
data: {
title: 'Sequelize to Prisma Guide'
}
})
Order
Here sequelize uses an array syntax that requires prior knowledge on the order of properties. Prisma's syntax is objectively better because we don't have to remember any property ordering and it uses simplistic object syntax compared to nested arrays.
Sequelize:
await models.Thread.findOne({
where: {
id: req.params.id
},
order: [['createdAt', 'DESC']]
})
Prisma:
const updateUser = await prisma.Threads.findFirst({
where: {
id: req.params.id
},
orderBy: {
createdAt: 'desc'
}
})
Limit
To set a limit on how many posts you want returned from your query, simply change the Sequelize property of limit
to take
. Neither library has an advantage here as which is best comes down to personal preference.
Sequelize:
const threads = await models.Thread.findAll({
limit: 5
})
Prisma:
const threads = await prisma.Threads.findMany({
take: 5
})
Operators
Sequelize requires you import an Op
object to reference the various operators it has available in its library. Honestly, how annoying. Prisma wins here since you can reference operators directly within your where clause without having to import anything.
Not
Sequelize:
const threads = await models.Thread.findAll({
where: {
slug: {
[Op.not]: req.params.slug
}
}
})
Prisma:
const threads = await prisma.Threads.findMany({
where: {
NOT: {
slug: req.params.slug
}
}
})
In
Sequelize:
await prisma.Threads.findAll({
where: {
CourseId: [22, 23]
}
})
Prisma:
await prisma.Threads.findMany({
where: {
CourseId: { in: [22, 23] }
}
})
Not-in
Sequelize:
const threads = await models.Thread.findAll({
where: {
slug: {
[Op.not]: ['post-1', 'post-2']
}
}
})
Prisma:
const threads = await prisma.Threads.findMany({
where: {
slug: {
notIn: ['post-1', 'post-2']
}
}
})
Delete
Sequelize uses a destroy
method while Prisma uses a delete
method for deleting rows. If using an id or int property for your Prisma query, make sure you parse your param to a number (req.params.id
might be a string depending on how you pass it to your backend).
Sequelize:
await models.Favorites.destroy({ where: { id: req.params.id } })
Prisma:
await prisma.Favorites.delete({
where: {
id: Number(req.params.id)
}
})
Create
The two are quite similar, the only difference is that Prisma requires you wrap your data in a data
property.
Sequelize:
await models.Threads.create({ title: 'My new post' })
Prisma:
await prisma.Threads.create({
data: {
title: 'My new post'
}
})