Overview

This section explains how to predict and control which fields of a model are returned in a Prisma Client API call by using the select and include options.

Unless otherwise noted, the examples on this page are based on the following Prisma schema:

model User {
id Int @id @default(autoincrement())
name String?
email String @unique
profileViews Int @default(0)
role Role @default(USER)
coinflips Boolean[]
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
enum Role {
USER
ADMIN
}

Selection sets

To understand which fields are being returned by a certain Prisma Client query, you need to be aware of its selection set.

The selection set defines which object properties the Prisma Client API call returns.

Consider the following example findOne invocation:

const result = await prisma.user.findOne({
where: { id: 1 },
})

The result of this API call is a plain old JavaScript object that might look similar to this:

{
id: 1,
name: "Alice",
email: "alice@prisma.io",
profileViews: 0,
role: "ADMIN",
coinflips: [true, false],
}

All the fields that are contained in this object are scalar fields, enums or arrays of scalar fields.

The default selection set

If the selection set is not manipulated (via select or include), a Prisma Client API call returns the default selection set for a model. It includes all scalar fields (including enums and arrays/scalar lists) fields of the model.

Considering the sample datamodel from above:

  • The default selection set for the User model includes id, name, email, profileViews, role and coinflips. It does not include posts because that's a relation and not a scalar field.
  • The default selection set for the Post model includes id, title and published. It does not include author because that's a relation and not a scalar field.

Manipulating the selection set

There are two ways how the default selection set can be manipulated to specify which fields should be returned by a Prisma Client API call:

  • Select exclusively (via select): When using select, the selection set only contains the fields that are explicitly provided as arguments to select.
  • Include additionally (via include): When using include, the default selection set gets extended with additional fields that are provided as arguments to include.

Note that you can nest select and include statements but they can't be provided right next to each other. For example, the following combination is allowed:

const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
})

And the following one is not allowed because select and include appear on the same level of nesting right next to each other:

const result = await prisma.user.findMany({
select: {
id: true,
name: true,
},
include: {
posts: true,
},
})

This case would be caught with the following exceptions:

Invalid `prisma.user.findMany()` invocation:
{
select: {
~~~~~~
id: true,
name: true
},
include: {
~~~~~~~
posts: true
}
}
Please either use `include` or `select`, but not both at the same time.

Both, select and include are available as options on the following methods:

select

When providing the select option to a Prisma Client API call, only those fields are included on the returned object that are explicitly specified. The select option is an object that contains all fields of a model with a boolean value indicating whether this field should be included in the response.

Type

The type of the select option is custom for each model. For example, for the User and Post models from above the types look as follows:

export type UserSelect = {
id?: boolean
name?: boolean
email?: boolean
role?: boolean
coinflips?: boolean
profileViews?: boolean
posts?: boolean | FindManyPostArgs
}
export type PostSelect = {
id?: boolean
title?: boolean
published?: boolean
author?: boolean | UserArgs
}

The types also contain relation fields which can be even further controlled with specific arguments:

export type UserArgs = {
select?: UserSelect | null
include?: UserInclude | null
}
export type FindManyPostArgs = {
select?: PostSelect | null
include?: PostInclude | null
where?: PostWhereInput | null
orderBy?: Enumerable<PostOrderByInput> | null
skip?: number | null
after?: PostWhereUniqueInput | null
before?: PostWhereUniqueInput | null
first?: number | null
last?: number | null
}

Examples

In this example, we're using select to exclusively select the name and profileViews fields of the returned User object:

const result = await prisma.user.findOne({
where: { id: 1 },
select: {
name: true,
profileViews: true,
},
})

The result object now looks as follows:

{
name: "Alice",
profileViews: 0
}

You can do the same on any other query listed above, e.g. on findMany:

const result = await prisma.user.findMany({
select: {
email: true,
role: true,
},
})

Since findMany returns an array of objects, result would now look as follows:

;[
{
email: 'alice@prisma.io',
role: 'ADMIN',
},
{
email: 'bob@prisma.io',
role: 'USER',
},
]

Here's how you can include additional fields of a relation:

const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
},
},
},
})

In this case, the result might look as follow:

;[
{
id: 1,
name: 'Alice',
posts: [
{ id: 1, title: 'Hello World' },
{ id: 2, title: 'Bye bye' },
],
},
{
id: 2,
name: 'Bob',
posts: [],
},
]

You can also nest the include option inside of the select option:

const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
})

This would result in the following structure for the result object:

;[
{
id: 1,
name: 'Alice',
posts: [
{
id: 1,
title: 'Hello World',
published: true,
author: {
id: 1,
name: 'Alice',
email: 'alice@prisma.io',
role: 'ADMIN',
coinflips: [true, false],
profileViews: 0,
},
},
{
id: 2,
title: 'Bye bye',
published: false,
author: {
id: 1,
name: 'Alice',
email: 'alice@prisma.io',
role: 'USER',
coinflips: [],
profileViews: 0,
},
},
],
},
]

Note that the author contains all fields of the User model's default selection set (scalars, arrays/scalar lists, enums).

include

Sometimes you want to directly include a relation when retrieving data from a database (this is sometimes called "eager loading"). To include the relations of a model in an API call, you can use the include options.

Type

The type of the include option is custom for each model. For example, for the User and Post models from above the types look as follows:

export type UserInclude = {
posts?: boolean | FindManyPostArgs
}
export type PostInclude = {
author?: boolean | UserArgs
}

The types contain only relation fields which can be even further controlled with specific arguments:

export type UserArgs = {
select?: UserSelect | null
include?: UserInclude | null
}
export type FindManyPostArgs = {
select?: PostSelect | null
include?: PostInclude | null
where?: PostWhereInput | null
orderBy?: Enumerable<PostOrderByInput> | null
skip?: number | null
after?: PostWhereUniqueInput | null
before?: PostWhereUniqueInput | null
first?: number | null
last?: number | null
}

Examples

const result = await prisma.user.findOne({
where: { id: 1 },
include: { posts: true },
})

The result object in this case contains the default selection set of the User model plus its posts relation:

{
id: 1,
name: "Alice",
email: "alice@prisma.io",
role: "ADMIM",
coinflips: [true],
profileViews: 0,
posts: [
{
id: 1,
title: "Hello World",
published: true
},
{
id: 2,
title: "Bye bye",
published: false
}
]
}

You can also nest include and select statements:

const result = await prisma.user.findOne({
where: { id: 1 },
include: {
posts: {
select: {
published: true,
title: true,
},
},
},
})

This would lead to the following structure of the result object:

{
id: 1,
name: "Alice",
email: "alice@prisma.io",
role: "USER",
coinflips: [true],
profileViews: 0,
posts: [
{
published: true,
title: "Hello World"
},
{
published: false,
title: "Bye bye"
}
]
}

The nesting and combinations can be arbitrarily deep:

const result = await prisma.user.findOne({
where: { id: 1 },
include: {
posts: {
select: {
published: true,
title: true,
author: {
select: {
id: true,
posts: {
select: {
title: true,
},
},
},
},
},
},
},
})

In this case, the result object would look as follows:

{
id: 1,
name: "Alice",
email: "alice@prisma.io",
role: "USER",
coinflips: [true],
profileViews: 0,
posts: [
{
published: true,
title: "Hello World",
author: {
id: 1,
posts: [
{
title: "Hello World"
},
{
title: "Bye bye"
}
]
}
},
{
published: false,
title: "Bye bye",
author: {
id: 1,
posts: [
{
title: "Hello World"
},
{
title: "Bye bye"
}
]
}
}
]
}
Edit this page on GitHub