apps/docs/content/docs/orm/prisma-schema/data-model/models.mdx
The data model definition part of the Prisma schema defines your application models (also called Prisma models). Models:
The following schema describes a blogging platform - the data model definition is highlighted:
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]
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:
model primitives) that define a number of fields, including relations between modelsenum primitives) (if your connector supports Enums)The corresponding database looks like this:
<details> <summary>A model maps to the underlying structures of the data source.</summary>model maps to a tablemodel maps to a collection</details>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.
The following query creates a User with nested Post and Category records:
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:
Customer, Order, Item and Invoice.User, Post, Photo and Message.There are two ways to define a data model:
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:
model Comment {
// Fields
}
model Tag {
// Fields
}
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:
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:
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
@mapa column name or enum value, and@@mapan 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.
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:
String or IntPost or Comment[]The following example extends the Comment and Tag models with several scalar types. Some fields include attributes:
model Comment {
id Int @id @default(autoincrement()) // [!code highlight]
title String // [!code highlight]
content String // [!code highlight]
}
model Tag {
name String @id // [!code highlight]
}
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 .
A relation field's type is another model - for example, a post (Post) can have multiple comments (Comment[]):
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
}
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 database type attributes describe the underlying database type:
model Post {
id Int @id
title String @db.VarChar(200)
content String
}
Type attributes are:
@db.Boolean, MySQL uses @db.TinyInt(1))@dbSee native database type attributes for the complete list.
The type of a field can be modified by appending either of two modifiers:
Note: You cannot combine type modifiers - optional lists are not supported.
The following example includes a scalar list and a list of related models:
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. :::
model Comment {
id Int @id @default(autoincrement())
title String // Required field
content String? // Optional field (nullable)
}
Fields without ? are required:
NOT NULL constraintsWhen you introspect a relational database, unsupported data types are added as Unsupported:
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.
:::
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):
model User {
id Int @id @default(autoincrement())
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@unique([firstName, lastName])
}
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:
isAdmin Boolean @default(false) // short form of @default(value: false)
See complete list of field and block attributes
An ID uniquely identifies individual records of a model. A model can only have one ID:
@id or an @@id, you must define a mandatory @unique field or @@unique block instead.@id attribute and a @map("_id") attribute.In relational databases, an ID can be defined by a single field using the @id attribute, or multiple fields using the @@id attribute.
In the following example, the User ID is represented by the id integer field:
model User {
id Int @id @default(autoincrement()) // [!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 a combination of the firstName and lastName fields:
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:
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 identifiersIn 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:
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.
:::
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:
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:
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.
:::
You can define default values for scalar fields using the @default attribute:
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:
5 (Int), "Hello" (String), false (Boolean)[5, 6, 8] (Int[]), ["Hello", "Goodbye"] (String[])now(), uuid(), cuid()@default("{ \"hello\": \"world\" }")See attribute functions for connector support details.
Unique attributes can be defined on a single field using @unique, or on multiple fields using @@unique:
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.
For MongoDB composite types, you can define unique constraints on nested fields:
type Address {
street String
number Int
}
model User {
id Int @id
email String
address Address
@@unique([email, address.number])
}
Define indexes via @@index:
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.
Enums are defined via the enum block when supported by your database:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
}
enum Role {
USER
ADMIN
}
:::warning Composite types are only available on MongoDB. :::
Composite types (embedded documents) allow embedding records inside other records:
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
The Prisma schema supports functions for default values:
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
uuid String @default(uuid())
}
Common functions: now(), uuid(), cuid(), autoincrement(), auto() (MongoDB ObjectId)
See relations documentation for relationship details.
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({ ... })
Prisma Client generates TypeScript types for your models:
export type User = {
id: number;
email: string;
name: string | null;
};
These types ensure type-safe database queries.
Every Prisma model must have at least one unique identifier:
@id or @@id for primary key@unique or @@unique for unique constraint