Working with One-to-Many Relations
1. Defining One-to-Many Relation
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
}
Side Marker
Parent (one) List field Post[]
Child (many) FK + @relation
2. Setting Foreign Key Field
Tip Detail
Index FK columns auto-indexed for joins
Composite FK Use array in fields/references
3. Configuring Back Reference
Side Field
User.posts Virtual relation, no DB column
Post.author Virtual; FK is authorId
4. Using Optional Foreign Keys
authorId Int?
author User? @relation(fields: [authorId], references: [id], onDelete: SetNull)
Effect Detail
Detached posts Posts can exist without an author
Cascade choice Pair optional FK with SetNull
5. Setting Relation Name
Use Case Example
Author + reviewer Two User relations on Post need names
Syntax @relation("AuthoredPosts", fields:[authorId], references:[id])
6. Configuring Referential Actions
Scenario Recommendation
User deleted → posts Cascade (remove posts)
Author optional SetNull
Audit log Restrict (preserve history)
const user = await prisma.user. findUnique ({
where: { id: 1 },
include: { posts: { where: { published: true }, take: 10 , orderBy: { createdAt: "desc" } } }
});
Option Detail
whereFilter included rows
take/skipLimit/offset included rows
orderBySort included rows
Operator Meaning
someAt least one related row matches
everyAll related rows match
noneZero related rows match
is/isNotFor to-one relations
await prisma.user. findMany ({
where: { posts: { some: { published: true } } }
});
const users = await prisma.user. findMany ({
include: { _count: { select: { posts: true } } }
});
Pattern Detail
_countUse inside include or select
Filtered count Pass where: { posts: { where: { published: true } } }
await prisma.user. findMany ({
orderBy: { posts: { _count: "desc" } }
});
Pattern Use
_countSort by number of related rows
Related field orderBy: { author: { name: "asc" } }