Working with Many-to-Many Relations

1. Using Implicit Many-to-Many

model Post {
  id   Int    @id @default(autoincrement())
  tags Tag[]
}
model Tag {
  id    Int    @id @default(autoincrement())
  posts Post[]
}
AspectDetail
Join tableAuto-named _PostToTag
No extra fieldsCan't store metadata on join

2. Defining Explicit Join Table

model PostTag {
  postId Int
  tagId  Int
  post   Post @relation(fields:[postId], references:[id], onDelete: Cascade)
  tag    Tag  @relation(fields:[tagId],  references:[id], onDelete: Cascade)
  @@id([postId, tagId])
}
WhenUse
Extra fieldse.g., addedAt, addedBy
Custom queriesNeed direct join-table access

3. Configuring Join Table Fields

FieldPurpose
Composite PK@@id([postId, tagId])
IndexesAdd @@index([tagId]) for reverse lookups
ActionsCascade on both FKs

4. Adding Extra Fields to Join Table

model PostTag {
  postId   Int
  tagId    Int
  addedAt  DateTime @default(now())
  addedBy  String?
  @@id([postId, tagId])
}
Common FieldsUse
createdAtAudit timestamp
positionOrdered membership
roleJoin role (e.g., owner/member)

5. Querying Many-to-Many Relations

const post = await prisma.post.findUnique({
  where: { id: 1 },
  include: { tags: true }
});
PatternDetail
ImplicitTags inlined directly
ExplicitInclude nested: postTags: { include: { tag: true } }

6. Connecting Existing Records

await prisma.post.update({
  where: { id: 1 },
  data: { tags: { connect: [{ id: 5 }, { id: 7 }] } }
});
OpEffect
connectAdd link to existing rows
setReplace entire set
OpEffect
disconnectRemove individual link
set: []Remove all links
Explicit joinUse delete on PostTag rows

8. Setting Multiple Relations

await prisma.post.update({
  where: { id: 1 },
  data: { tags: { set: [{ id: 1 }, { id: 2 }, { id: 3 }] } }
});
NoteDetail
setIdempotent; current = provided list
MixCombine connect+disconnect in one update
await prisma.post.findMany({
  where: { tags: { some: { name: { in: ["typescript", "react"] } } } }
});
FilterUse
someAt least one tag matches
everyAll tags satisfy condition
noneNo matching tags

10. Managing Relation Ordering

ApproachDetail
ImplicitNo inherent order; sort included list via orderBy
ExplicitAdd position Int in join table
Stable orderingCombine position + createdAt