Welcome to PrismaHandsOn – your go-to resource for hands-on learning with Prisma ORM! Whether you're a beginner or an experienced developer looking to level up your skills, this repository is designed to guide you through the practical aspects of using Prisma in real-world scenarios.
1. Finding All Records:
- Use
prisma.model.findMany()
to retrieve all records of a specific model. - Example:
const allUsers = await prisma.user.findMany()
2. Finding the First Record:
- Use
prisma.model.findFirst()
to retrieve the first record matching your criteria. - Example:
const firstUser = await prisma.user.findFirst({ where: { name: 'Alice' } })
3. Finding the First Record or Throwing an Error:
- Use
prisma.model.findFirstOrThrow()
to retrieve the first record or throw an error if none is found. - Example:
const user = await prisma.user.findFirstOrThrow({ where: { id: 1 } })
4. Finding a Unique Record:
- Use
prisma.model.findUnique()
to retrieve a single record based on unique fields, such as an email address. - Example:
const user = await prisma.user.findUnique({ where: { email: 'johndoe@example.com' } })
5. Finding a Unique Record or Throwing an Error:
- Use
prisma.model.findUniqueOrThrow()
to retrieve a unique record or throw an error if none or multiple are found.
6. Selecting Specific Fields:
- Use the
select
option to fetch only the desired fields, improving performance. - Example:
const users = await prisma.user.findMany({ select: { name: true, email: true } })
1. Fluent API:
- Prisma offers a fluent API for navigating relationships between models.
- Example:
const posts = await prisma.user.findUnique({ where: { email: 'johndoe@example.com' } }).posts()
2. Nested Reads:
- Fetch related data in a single query using
include
or nestedselect
. - Example:
const userWithPosts = await prisma.user.findUnique({ where: { email: 'johndoe@example.com' }, include: { posts: true } })
3. Relation Filters:
- Filter related records using
where
within nested reads. - Example:
const userWithRecentPosts = await prisma.user.findUnique({ where: { email: 'johndoe@example.com' }, include: { posts: { where: { published: true } } } })
1. AND:
- Combines multiple conditions using
and
within thewhere
clause. - Example:
const users = await prisma.user.findMany({ where: { age: { gt: 25 }, city: 'London' } })
2. Contains:
- Checks if a string field contains a substring using
contains
. - Example:
const posts = await prisma.post.findMany({ where: { title: { contains: 'Prisma' } } })
3. Equality:
- Compares values for exact equality using
==
. - Example:
const user = await prisma.user.findUnique({ where: { email: 'johndoe@example.com' } })
4. Greater Than:
- Finds values greater than a specified value using
gt
. - Example:
const expensiveProducts = await prisma.product.findMany({ where: { price: { gt: 100 } } })
5. In Array:
- Checks if a value is present within an array using
in
. - Example:
const activeUsers = await prisma.user.findMany({ where: { status: { in: ['active', 'pending'] } } })
6. NOT:
- Negates a condition using
not
. - Example:
const nonAdminUsers = await prisma.user.findMany({ where: { role: { not: 'admin' } } })
7. OR:
- Combines multiple conditions using
or
within thewhere
clause. - Example:
const posts = await prisma.post.findMany({ where: { OR: [{ title: { contains: 'Prisma' } }, { content: { contains: 'ORM' } }] } })
8. Starts With:
- Checks if a string field starts with a specific substring using
startsWith
. - Example:
const users = await prisma.user.findMany({ where: { name: { startsWith: 'A' } } })
1. Cursor:
- Concept: Cursor-based pagination relies on a unique value ("cursor") associated with each record, typically its ID or a timestamp. You request subsequent pages by providing the last known cursor in your query.
- How it works:
- Specify the
orderBy
option in your query to define the sorting order. - Use the
first
orlast
option to set the number of records per page. - Include the
cursor
argument with the value from the previous response for subsequent pages.
- Specify the
- Advantages:
- Efficient for large datasets: Only fetches needed pages, minimizing database load.
- Random access: Jump to any page regardless of order.
- Disadvantages:
- Requires consistent sorting: Cursor needs to be unique and ordered based on your sorting criteria.
- Complex logic: Managing and handling cursors can be intricate.
2. Limit-Offset:
- Concept: This traditional pagination method retrieves a specific number of records ("limit") starting from a given offset.
- How it works:
- Define the
skip
option to specify the offset (number of records to skip initially). - Set the
take
option to determine the number of records to retrieve.
- Define the
- Advantages:
- Simpler implementation: Easier to understand and set up.
- Predictable results: Consistent ordering within each page.
- Disadvantages:
- Inefficient for large datasets: Fetches all records up to the offset, even if not displayed.
- Limited access: Jumping to specific pages can be slow, needing multiple queries.
3. Sort:
- Concept: Defining the order in which your data is presented.
- How it works:
- Use the
orderBy
option in your query, specifying the field(s) and sorting direction (ascending/descending). - You can sort by multiple fields, prioritize them using nested arrays.
- Use the
- Benefits:
- Organizes data for better user experience.
- Enables efficient filtering based on sorted criteria.
Choosing the right method:
- For large datasets, cursor-based pagination is generally preferred due to its efficiency.
- If dealing with smaller datasets or prioritizing simplicity, limit-offset might be suitable.
- Consider user needs and the size of your data when making the choice.
- Prisma generates type-safe queries based on your schema, ensuring correctness.
- Queries are automatically optimized for performance.
- Nested reads reduce the number of database round trips.
- Relation filters allow for precise data retrieval.
- Always import the Prisma Client in your code:
const { PrismaClient } = require('@prisma/client');
- Instantiate the client:
const prisma = new PrismaClient();
- Close the client after use:
await prisma.$disconnect();