Models
Learn about the concepts for building your data model with Prisma: Models, scalar types, enums, attributes, functions, IDs, default values and more
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:
datasource db {
provider = "postgresql"
}
generator client {
provider = "prisma-client"
output = "./generated"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String
posts Post[]
}
enum Role {
USER
ADMIN
} The data model definition is made up of:
- Models (
modelprimitives) that define a number of fields, including relations between models - Enums (
enumprimitives) (if your connector supports Enums) - Attributes and functions that change the behavior of fields and models
The corresponding database looks like this:

A model maps to the underlying structures of the data source.
- In relational databases like PostgreSQL and MySQL, a
modelmaps to a table - In MongoDB, a
modelmaps 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.
The following query creates a User with nested Post and Category records:
const user = await prisma.user.create({
data: {
email: "ariadne@prisma.io",
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,ItemandInvoice. - In a social media application you probably have models like
User,Post,PhotoandMessage.
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:
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:
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.
Defining fields
The properties of a model are called fields, which consist of:
- A field name
- A field type
- Optional type modifiers
- Optional attributes, including native database type attributes
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,
StringorInt - Model types (the field is then called relation field) - for example
PostorComment[]
Scalar fields
The following example extends the Comment and Tag models with several scalar types. Some fields include attributes:
model Comment {
id Int @id @default(autoincrement())
title String
content String
}
model Tag {
name String @id
}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[]):
model Post {
id Int @id @default(autoincrement())
// Other fields
comments Comment[] // A post can have many comments
}
model Comment {
id Int
// Other fields
post Post @relation(fields: [postId], references: [id]) // A comment can have one post
postId Int
}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:
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:
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:
model Post {
id Int @id @default(autoincrement())
comments Comment[] // A list of comments
keywords String[] // A scalar list
}Scalar lists are only supported if the database connector supports them natively or at a Prisma ORM level.
Optional and mandatory fields
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 NULLconstraints - 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:
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.
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):
model User {
id Int @id @default(autoincrement())
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
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
@idor an@@id, you must define a mandatory@uniquefield or@@uniqueblock instead. - In MongoDB, an ID must be a single field that defines an
@idattribute 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:
model User {
id Int @id @default(autoincrement())
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:
model User {
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@id([firstName, lastName])
}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])
}The firstName_lastName field will now be named fullName instead.
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:
model User {
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}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:
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
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")
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}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:
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:
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:
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:
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:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
}
enum Role {
USER
ADMIN
}Defining composite types (MongoDB)
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
Using functions
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)
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:
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:
@idor@@idfor primary key@uniqueor@@uniquefor unique constraint