Back to Prisma

Models

apps/docs/content/docs/orm/prisma-schema/data-model/models.mdx

latest23.3 KB
Original Source

The data model definition part of the Prisma schema defines your application models (also called Prisma models). Models:

  • Represent the entities of your application domain
  • Map to the tables (relational databases like PostgreSQL) or collections (MongoDB) in your database
  • Form the foundation of the queries available in the generated Prisma Client API
  • When used with TypeScript, Prisma Client provides generated type definitions for your models and any variations of them to make database access entirely type safe.

The following schema describes a blogging platform - the data model definition is highlighted:

prisma
datasource db {
  provider = "postgresql"
}

generator client {
  provider = "prisma-client"
  output   = "./generated"
}

model User { // [!code highlight]
  id      Int      @id @default(autoincrement()) // [!code highlight]
  email   String   @unique // [!code highlight]
  name    String? // [!code highlight]
  role    Role     @default(USER) // [!code highlight]
  posts   Post[] // [!code highlight]
  profile Profile? // [!code highlight]
} // [!code highlight]

model Profile { // [!code highlight]
  id     Int    @id @default(autoincrement()) // [!code highlight]
  bio    String // [!code highlight]
  user   User   @relation(fields: [userId], references: [id]) // [!code highlight]
  userId Int    @unique // [!code highlight]
} // [!code highlight]

model Post { // [!code highlight]
  id         Int        @id @default(autoincrement()) // [!code highlight]
  createdAt  DateTime   @default(now()) // [!code highlight]
  updatedAt  DateTime   @updatedAt // [!code highlight]
  title      String // [!code highlight]
  published  Boolean    @default(false) // [!code highlight]
  author     User       @relation(fields: [authorId], references: [id]) // [!code highlight]
  authorId   Int // [!code highlight]
  categories Category[] // [!code highlight]
} // [!code highlight]

model Category { // [!code highlight]
  id    Int    @id @default(autoincrement()) // [!code highlight]
  name  String // [!code highlight]
  posts Post[] // [!code highlight]
} // [!code highlight]

enum Role { // [!code highlight]
  USER // [!code highlight]
  ADMIN // [!code highlight]
} // [!code highlight]
prisma
datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User { // [!code highlight]
  id      String   @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  email   String   @unique // [!code highlight]
  name    String? // [!code highlight]
  role    Role     @default(USER) // [!code highlight]
  posts   Post[] // [!code highlight]
  profile Profile? // [!code highlight]
} // [!code highlight]

model Profile { // [!code highlight]
  id     String @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  bio    String // [!code highlight]
  user   User   @relation(fields: [userId], references: [id]) // [!code highlight]
  userId String @unique @db.ObjectId // [!code highlight]
} // [!code highlight]

model Post { // [!code highlight]
  id          String     @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  createdAt   DateTime   @default(now()) // [!code highlight]
  title       String // [!code highlight]
  published   Boolean    @default(false) // [!code highlight]
  author      User       @relation(fields: [authorId], references: [id]) // [!code highlight]
  authorId    String     @db.ObjectId // [!code highlight]
  categoryIDs String[]   @db.ObjectId // [!code highlight]
  categories  Category[] @relation(fields: [categoryIDs], references: [id]) // [!code highlight]
} // [!code highlight]

model Category { // [!code highlight]
  id      String   @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  name    String // [!code highlight]
  postIDs String[] @db.ObjectId // [!code highlight]
  posts   Post[]   @relation(fields: [postIDs], references: [id]) // [!code highlight]
} // [!code highlight]

enum Role { // [!code highlight]
  USER // [!code highlight]
  ADMIN
}

The data model definition is made up of:

The corresponding database looks like this:

<details> <summary>A model maps to the underlying structures of the data source.</summary>
  • In relational databases like PostgreSQL and MySQL, a model maps to a table
  • In MongoDB, a model maps to a collection

Note: In the future there might be connectors for non-relational databases and other data sources. For example, for a REST API it would map to a resource.

</details>

The following query creates a User with nested Post and Category records:

ts
const user = await prisma.user.create({
  data: {
    email: "[email protected]",
    name: "Ariadne",
    posts: {
      create: [
        {
          title: "My first day at Prisma",
          categories: { create: { name: "Office" } },
        },
        {
          title: "How to connect to a SQLite database",
          categories: { create: [{ name: "Databases" }, { name: "Tutorials" }] },
        },
      ],
    },
  },
});

Your data model reflects your application domain. For example:

  • In an ecommerce application you probably have models like Customer, Order, Item and Invoice.
  • In a social media application you probably have models like User, Post, Photo and Message.

Introspection and migration

There are two ways to define a data model:

  • Write the data model manually and use Prisma Migrate: You can write your data model manually and map it to your database using Prisma Migrate. In this case, the data model is the single source of truth for the models of your application.
  • Generate the data model via introspection: When you have an existing database or prefer migrating your database schema with SQL, you generate the data model by introspecting your database. In this case, the database schema is the single source of truth for the models of your application.

Defining models

Models represent the entities of your application domain. Models are represented by model blocks and define a number of fields. In the example data model above, User, Profile, Post and Category are models.

A blogging platform can be extended with the following models:

prisma
model Comment {
  // Fields
}

model Tag {
  // Fields
}

Mapping model names to tables or collections

Prisma model naming conventions (singular form, PascalCase) do not always match table names in the database. A common approach for naming tables/collections in databases is to use plural form and snake_case notation - for example: comments. When you introspect a database with a table named comments, the resulting Prisma model will look like this:

prisma
model comments {
  // Fields
}

However, you can still adhere to the naming convention without renaming the underlying comments table in the database by using the @@map attribute:

prisma
model Comment {
  // Fields

  @@map("comments")
}

With this model definition, Prisma ORM automatically maps the Comment model to the comments table in the underlying database.

Note: You can also @map a column name or enum value, and @@map an enum name.

@map and @@map allow you to tune the shape of your Prisma Client API by decoupling model and field names from table and column names in the underlying database.

Defining fields

The properties of a model are called fields, which consist of:

A field's type determines its structure, and fits into one of two categories:

  • Scalar types (includes enums) that map to columns (relational databases) or document fields (MongoDB) - for example, String or Int
  • Model types (the field is then called relation field) - for example Post or Comment[]

Scalar fields

The following example extends the Comment and Tag models with several scalar types. Some fields include attributes:

prisma
model Comment {
  id      Int    @id @default(autoincrement()) // [!code highlight]
  title   String // [!code highlight]
  content String // [!code highlight]
}

model Tag {
  name String @id // [!code highlight]
}
prisma
model Comment {
  id      String @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  title   String // [!code highlight]
  content String // [!code highlight]
}

model Tag {
  name String @id @map("_id") // [!code highlight]
}

See complete list of scalar field types .

Relation fields

A relation field's type is another model - for example, a post (Post) can have multiple comments (Comment[]):

prisma
model Post {
  id       Int       @id @default(autoincrement())
  // Other fields
  comments Comment[] // A post can have many comments // [!code highlight]
}

model Comment {
  id     Int
  // Other fields
  post   Post @relation(fields: [postId], references: [id]) // A comment can have one post // [!code highlight]
  postId Int
}
prisma
model Post {
  id       String    @id @default(auto()) @map("_id") @db.Objectid
  // Other fields
  comments Comment[] // A post can have many comments // [!code highlight]
}

model Comment {
  id     String @id @default(auto()) @map("_id") @db.Objectid
  // Other fields
  post   Post   @relation(fields: [postId], references: [id]) // A comment can have one post // [!code highlight]
  postId String @db.ObjectId
}

Refer to the relations documentation for more examples and information about relationships between models.

Native types mapping

Native database type attributes describe the underlying database type:

prisma
model Post {
  id      Int    @id
  title   String @db.VarChar(200)
  content String
}

Type attributes are:

  • Specific to the underlying provider (e.g., PostgreSQL uses @db.Boolean, MySQL uses @db.TinyInt(1))
  • Written in PascalCase and prefixed by @db
  • Only added during introspection if the native type differs from the default

See native database type attributes for the complete list.

Type modifiers

The type of a field can be modified by appending either of two modifiers:

  • [] Make a field a list
  • ? Make a field optional

Note: You cannot combine type modifiers - optional lists are not supported.

Lists

The following example includes a scalar list and a list of related models:

prisma
model Post {
  id       Int       @id @default(autoincrement())
  comments Comment[] // A list of comments
  keywords String[]  // A scalar list
}

:::note Scalar lists are only supported if the database connector supports them natively or at a Prisma ORM level. :::

Optional and mandatory fields

prisma
model Comment {
  id      Int     @id @default(autoincrement())
  title   String       // Required field
  content String?      // Optional field (nullable)
}

Fields without ? are required:

  • Relational databases: Represented via NOT NULL constraints
  • Prisma Client: TypeScript types enforce these fields at compile time

Unsupported types

When you introspect a relational database, unsupported data types are added as Unsupported:

prisma
location    Unsupported("POLYGON")?

Fields of type Unsupported don't appear in the generated Prisma Client API, but you can still use raw database access to query them.

:::note The MongoDB connector doesn't support Unsupported types because it supports all scalar types. :::

Defining attributes

Attributes modify the behavior of fields or model blocks. The following example includes three field attributes (@id , @default , and @unique ) and one block attribute (@@unique):

prisma
model User {
  id        Int     @id @default(autoincrement())
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@unique([firstName, lastName])
}
prisma
model User {
  id        String  @id @default(auto()) @map("_id") @db.ObjectId
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@unique([firstName, lastName])
}

Some attributes accept arguments - for example, @default accepts true or false:

prisma
isAdmin   Boolean @default(false) // short form of @default(value: false)

See complete list of field and block attributes

Defining an ID field

An ID uniquely identifies individual records of a model. A model can only have one ID:

  • In relational databases, the ID can be a single field or based on multiple fields. If a model does not have an @id or an @@id, you must define a mandatory @unique field or @@unique block instead.
  • In MongoDB, an ID must be a single field that defines an @id attribute and a @map("_id") attribute.

Defining IDs in relational databases

In relational databases, an ID can be defined by a single field using the @id attribute, or multiple fields using the @@id attribute.

Single field IDs

In the following example, the User ID is represented by the id integer field:

prisma
model User {
  id      Int      @id @default(autoincrement()) // [!code highlight]
  email   String   @unique
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}
Composite IDs

In the following example, the User ID is represented by a combination of the firstName and lastName fields:

prisma
model User {
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@id([firstName, lastName]) // [!code highlight]
}

By default, the name of this field in Prisma Client queries will be firstName_lastName.

You can also provide your own name for the composite ID using the @@id attribute's name field:

prisma
model User {
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@id(name: "fullName", fields: [firstName, lastName]) // [!code highlight]
}

The firstName_lastName field will now be named fullName instead.

:::info

Refer to the documentation on working with composite IDs to learn how to interact with a composite ID in Prisma Client.

:::

@unique fields as unique identifiers

In the following example, users are uniquely identified by a @unique field. Because the email field functions as a unique identifier for the model (which is required), it must be mandatory:

prisma
model User {
  email   String   @unique // [!code highlight]
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}

:::info

Constraint names in relational databases

You can optionally define a custom primary key constraint name in the underlying database.

:::

Defining IDs in MongoDB

The MongoDB connector has specific rules for defining an ID field that differs from relational databases. An ID must be defined by a single field using the @id attribute and must include @map("_id").

In the following example, the User ID is represented by the id string field that accepts an auto-generated ObjectId:

prisma
model User {
  id      String   @id @default(auto()) @map("_id") @db.ObjectId // [!code highlight]
  email   String   @unique
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}

In the following example, the User ID is represented by the id string field that accepts something other than an ObjectId - for example, a unique username:

prisma
model User {
  id      String   @id @map("_id") // [!code highlight]
  email   String   @unique
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}

:::warning

MongoDB does not support @@id

MongoDB does not support composite IDs, which means you cannot identify a model with a @@id block.

:::

Defining a default value

You can define default values for scalar fields using the @default attribute:

prisma
model Post {
  id         Int        @id @default(autoincrement())
  createdAt  DateTime   @default(now())
  title      String
  published  Boolean    @default(false)
  data       Json       @default("{ \"hello\": \"world\" }")
}

Default values can be:

  • Static values: 5 (Int), "Hello" (String), false (Boolean)
  • Lists: [5, 6, 8] (Int[]), ["Hello", "Goodbye"] (String[])
  • Functions: now(), uuid(), cuid()
  • JSON: Use escaped strings, e.g., @default("{ \"hello\": \"world\" }")

See attribute functions for connector support details.

Defining a unique field

Unique attributes can be defined on a single field using @unique, or on multiple fields using @@unique:

prisma
model User {
  id    Int     @id @default(autoincrement())
  email String  @unique      // Single field unique
  name  String?
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  authorId Int

  @@unique([authorId, title]) // Composite unique
}

You can customize the constraint name with the name field: @@unique(name: "authorTitle", [authorId, title])

See working with composite unique identifiers for Prisma Client usage.

Composite type unique constraints (MongoDB)

For MongoDB composite types, you can define unique constraints on nested fields:

prisma
type Address {
  street String
  number Int
}

model User {
  id      Int     @id
  email   String
  address Address

  @@unique([email, address.number])
}

Defining an index

Define indexes via @@index:

prisma
model Post {
  id      Int     @id @default(autoincrement())
  title   String
  content String?

  @@index([title, content])
}

For MongoDB composite types, use dot notation: @@index([address.city.name])

See custom index names for naming customization.

Defining enums

Enums are defined via the enum block when supported by your database:

prisma
model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  role  Role    @default(USER)
}

enum Role {
  USER
  ADMIN
}

Defining composite types (MongoDB)

:::warning Composite types are only available on MongoDB. :::

Composite types (embedded documents) allow embedding records inside other records:

prisma
model Product {
  id     String  @id @default(auto()) @map("_id") @db.ObjectId
  name   String
  photos Photo[]
}

type Photo {
  height Int
  width  Int
  url    String
}

Supported attributes in composite types: @default, @map, native types (@db.ObjectId)

Not supported: @unique, @id, @relation, @ignore, @updatedAt

Using functions

The Prisma schema supports functions for default values:

prisma
model Post {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  uuid      String   @default(uuid())
}

Common functions: now(), uuid(), cuid(), autoincrement(), auto() (MongoDB ObjectId)

Relations

See relations documentation for relationship details.

Models in Prisma Client

Queries (CRUD)

Every model generates CRUD queries in the Prisma Client API:

findMany() | findFirst() | findUnique() | create() | update() | upsert() | delete() | createMany() | updateMany() | deleteMany()

Access via the lowercase model name property: prisma.user.create({ ... })

Type definitions

Prisma Client generates TypeScript types for your models:

ts
export type User = {
  id: number;
  email: string;
  name: string | null;
};

These types ensure type-safe database queries.

Limitations

Every Prisma model must have at least one unique identifier:

  • @id or @@id for primary key
  • @unique or @@unique for unique constraint