Prisma relations

By

Learn how Prisma relations work by linking User and Tweet models with @relation, connecting records, and loading related data with include when you query.

~~~

Prisma relations let you link two models in your schema, so you can create and query related records without writing joins by hand. They solve a huge problem with databases and data handling.

Suppose you have a list of users in your app, that create tweets (imagine Twitter).

In your schema you can define the relation between those 2 entities in this way:

model Tweet {
  id Int @id @default(autoincrement()) 
  text String
  author User @relation(fields: [authorId], references: [id])
  authorId Int
}

model User {
  id Int @default(autoincrement()) @id
  tweets Tweet[]
}

This is a one-to-many relation: one user has many tweets, each tweet has one author.

Look at the Tweet model. It has two fields dedicated to the relation. authorId is a real column in the database, holding the id of the user. author is the relation field: it doesn’t exist as a column, it’s what lets you work with the related User in your code. The @relation attribute ties them together, saying authorId references the id field of User.

On the User side, tweets Tweet[] is the other half of the relation. It’s virtual too, no column in the database. It gives you access to all the tweets of a user.

When you create a new tweet you associate it with a user with id 1 in this way:

await prisma.tweet.create({
  data: {
    text: req.body.content,
    author: {
      connect: { id: 1 }
    }
  }
})

connect links the new tweet to an existing user. If no user with id 1 exists, Prisma throws an error instead of creating an orphan tweet, which is what you want.

You can also create a user and populate the database with 2 tweets associated to it, all in a single query:

await prisma.user.create({
  data: {
    tweets: {
      create: [
        { text: 'test' },
        { text: 'test2' },
      ]
    }
  }
})

Here create (instead of connect) builds the related records from scratch.

Then you can retrieve the author information when you get tweets, with:

await prisma.tweet.findMany({
  include: {
    author: true
  }
})

Each tweet in the result now carries a full author object.

Here’s the pitfall that catches everyone at least once: Prisma does not load relations by default. Run findMany() without include and you get the scalar fields only, so tweet.authorId is there but tweet.author is undefined. If your code suddenly can’t read tweet.author.name, the missing include is almost always the reason.

Tagged: Database · All topics
~~~

Related posts about database: