Object Relation Mapper(ORM) is a technique of storing, retrieving, updating and deleting data from the database. ORMs let us define our models as classes that map to tables in a database.
When it comes to ORM there are many choices available to us like Sequelize, TypeORM, Knex, Drizzle and Prisma.
In this article we will cover Prisma, which is a top tier choice for ORM in your next application.
Prisma is an open source next-generation Node.js and TypeScript ORM. It describes itself as a “next-generation ORM” that makes working with databases easy for application developers.
It's is written in Typescript, which leads us to type-safe database schemas. Of course, everything needs to be well set to define what that database will look like. It abstracts developers from writing database queries, thus ensuring we write safe database access schemas.
The most awesome thing is the Prisma-client to set up and write database, model data, data validation, and describe the relationships between different data fields. Not only that it has a migration tool and a supercool GUI to visualize your data.
Tools provided out of the box:
Prisma Client: Auto-generated and type-safe Prisma query builder
Prisma Migrate: Migration system
Prisma Studio: A modern GUI for browsing and managing data in your database
Connect Prisma with DB
We will follow the documentation to get started with Prisma. You can read and also take a reference to the documentation.
For a demo we are using Prisma along with Typescript in our sample Node project connect with MongoDB instance in Railway.
We need a database connection string, we will get a MongoDB database connection URL from Railway here.
npx prisma init --datasource-provider mongodb
We will set the url field of the datasource block in our prisma schema to our recently created database connection URL.
Set, the url is set via an environment variable which is defined in .env:
DATABASE_URL="******"
Modeling data
We can start with modelling our data for our application. Prisma schema provides an intuitive way to model data. Add the following models to your schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
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
name String?
image String
company String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
emailVerified DateTime?
password String
}
model Products {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String @unique
description String
price String
size String
quantity Int
image String
createdAt DateTime @default(now())
}
enum Role {
User
Admin
Buyer
Seller
}
We created our data model.
We are building something like a marketplace where users can upload list of products to the Marketplace. And there are list of products which we want to seed the DB with along with the new user created.
We need to run the two commands so that we can setup the documents and tables needed for our application.
npx prisma generate
This command will generate the needed tables to store our data for our application using the data model we defined.
npx prisma studio
This will spin a GUI where we can take a look into when we have the tables and/or data inserted into our DB.
Adding Fake data
Before starting seeding our database we need some fake data. To generate some decent realistic fake data we are using two libraries.
Lets install them both.
npm i @ngneat/falso @faker-js/faker
We will also install a library to hash the fake user password that is created.
@types/bcryptjs bcryptjs
Let's create a new file and name it seed.ts
import bcrypt from 'bcryptjs';
import { randBetweenDate, randNumber, randProduct } from "@ngneat/falso";
import { faker } from "@faker-js/faker";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const main = async () => {
try{
await prisma.products.deleteMany();
const email = faker.internet.email('ishan', 'manandhar', 'example.fakerjs.dev');
const companyName = faker.company.companyName()
const hashedPassword = await bcrypt.hash('my_secure_password', 10);
await prisma.products.deleteMany(); //delete existing products
const fakeProducts = randProduct({
length: 300,
});
// cleanup the existing database
await prisma.user.delete({ where: { email } }).catch(() => {
// delete existing user found with same email
});
await prisma.user.create({
data: {
name: 'ishan',
image: '',
email: email,
password: hashedPassword,
company: companyName
},
});
for (let index = 0; index < fakeProducts.length; index++) {
const product = fakeProducts[index];
const name = faker.commerce.productName();
await prisma.products.upsert({
where: {
title: name,
},
create: {
title: name,
description: faker.lorem.paragraph() || product?.description,
price: faker.commerce.price(),
image: faker.image.abstract(640, 480, true),
quantity: randNumber({ min: 10, max: 100 }),
size: faker.random.numeric(),
createdAt: randBetweenDate({
from: new Date("10/07/2020"),
to: new Date(),
}),
},
update: {},
});
}
console.log(`Database has been seeded. 🌱`);
}
catch(error){
throw error;
}
}
main().catch((err) => {
console.warn("Error While generating Seed: \n", err);
});
Lets run the seed file with the command
npx prisma db seed
After sucessfully running the seed file we can head to our terminal and run npx prisma studio
to see our data added to our documents.
Yes, we have done it!
Conclusion
Prisma is such an awesome ORM that has a best developer experience(DX), documentation, observability support and end-to-end TypeScript coverage we can ever get.
It has made working with databases feel so intuitive and straightforward from the data modeling, running, migrations, writing the queries, and integrating it with the API's.
You can learn more from the Prisma official docs here.
Happy Coding!
Top comments (0)