본문으로 건너뛰기

중첩 읽기

중첩 읽기를 사용하면 데이터베이스의 여러 테이블에서 관련 데이터를 읽을 수 있습니다. 사용자 및 해당 사용자의 게시물이 그 예입니다.

다음이 가능합니다.

  • include를 사용하여 질의 응답에 사용자의 게시물이나 프로필과 같은 관련 레코드를 포함함
  • 중첩 select를 사용하여 관련 레코드의 특정 필드를 포함함. include 내부에 select를 중첩할 수도 있음

다음 예시에서는 단일 사용자와 해당 사용자의 게시물을 반환합니다.

ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
include: {
posts: true,
},
})
ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
include: {
posts: true,
},
})
결과
ts
{
id: 19,
name: null,
email: 'emma@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
posts: [
{
id: 20,
title: 'My first post',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0
},
{
id: 21,
title: 'How to make cookies',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0
}
]
}
결과
ts
{
id: 19,
name: null,
email: 'emma@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
posts: [
{
id: 20,
title: 'My first post',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0
},
{
id: 21,
title: 'How to make cookies',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0
}
]
}

특정 관계의 모든 필드 포함하기

다음 예시에서는 title 필드에 cookies 단어가 포함된 모든 게시물과 각 게시물의 작성자를 반환합니다. 결과에는 모든 작성자 필드가 포함됩니다.

ts
const getPosts = await prisma.post.findMany({
where: {
title: {
contains: 'cookies',
},
},
include: {
author: true, // 모든 필드를 반환합니다.
},
})
ts
const getPosts = await prisma.post.findMany({
where: {
title: {
contains: 'cookies',
},
},
include: {
author: true, // 모든 필드를 반환합니다.
},
})
결과
ts
[
{
id: 17,
title: 'How to make cookies',
published: true,
authorId: 16,
comments: null,
views: 0,
likes: 0,
author: {
id: 16,
name: null,
email: 'orla@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
},
},
{
id: 21,
title: 'How to make cookies',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0,
author: {
id: 19,
name: null,
email: 'emma@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
},
},
]
결과
ts
[
{
id: 17,
title: 'How to make cookies',
published: true,
authorId: 16,
comments: null,
views: 0,
likes: 0,
author: {
id: 16,
name: null,
email: 'orla@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
},
},
{
id: 21,
title: 'How to make cookies',
published: true,
authorId: 19,
comments: null,
views: 0,
likes: 0,
author: {
id: 19,
name: null,
email: 'emma@prisma.io',
profileViews: 0,
role: 'USER',
coinflips: [],
},
},
]

깊이 중첩된 관계 포함하기

관계의 관계를 포함하도록 include 옵션을 중첩할 수 있습니다.

다음 예시는 사용자의 게시물과 각 게시물의 카테고리를 반환합니다.

ts
const user = await prisma.user.findMany({
include: {
posts: {
include: {
categories: true,
},
},
},
})
ts
const user = await prisma.user.findMany({
include: {
posts: {
include: {
categories: true,
},
},
},
})
결과
ts
{
"id": 40,
"name": "Yvette",
"email": "yvette@prisma.io",
"profileViews": 0,
"role": "USER",
"coinflips": [],
"testing": [],
"city": null,
"country": "Sweden",
"posts": [
{
"id": 66,
"title": "How to make an omelette",
"published": true,
"authorId": 40,
"comments": null,
"views": 0,
"likes": 0,
"categories": [
{
"id": 3,
"name": "Easy cooking"
}
]
},
{
"id": 67,
"title": "How to eat an omelette",
"published": true,
"authorId": 40,
"comments": null,
"views": 0,
"likes": 0,
"categories": []
}
]
}
결과
ts
{
"id": 40,
"name": "Yvette",
"email": "yvette@prisma.io",
"profileViews": 0,
"role": "USER",
"coinflips": [],
"testing": [],
"city": null,
"country": "Sweden",
"posts": [
{
"id": 66,
"title": "How to make an omelette",
"published": true,
"authorId": 40,
"comments": null,
"views": 0,
"likes": 0,
"categories": [
{
"id": 3,
"name": "Easy cooking"
}
]
},
{
"id": 67,
"title": "How to eat an omelette",
"published": true,
"authorId": 40,
"comments": null,
"views": 0,
"likes": 0,
"categories": []
}
]
}

특정 관계 필드 선택하기

중첩 select를 사용하여 반환할 관계 필드의 하위 집합을 선택할 수 있습니다.

예를 들어 다음 질의는 사용자의 name과 각 관련 게시물의 title를 반환합니다.

ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: {
name: true,
posts: {
select: {
title: true,
},
},
},
})
ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: {
name: true,
posts: {
select: {
title: true,
},
},
},
})
결과
ts
{
name: "Elsa",
posts: [ { title: 'My first post' }, { title: 'How to make cookies' } ]
}
결과
ts
{
name: "Elsa",
posts: [ { title: 'My first post' }, { title: 'How to make cookies' } ]
}

include 내부에 select를 중첩할 수도 있습니다.

다음 예시에서는 각 게시물의 모든 User 필드와 title 필드를 반환합니다.

ts
const getUser = await prisma.user.findUnique({
where: {
id: 1,
},
// select: { name: true } <-- 불가능
include: {
posts: {
select: {
title: true,
},
},
},
})
ts
const getUser = await prisma.user.findUnique({
where: {
id: 1,
},
// select: { name: true } <-- 불가능
include: {
posts: {
select: {
title: true,
},
},
},
})
결과
ts
{
"id": 1,
"name": null,
"email": "martina@prisma.io",
"profileViews": 0,
"role": "USER",
"coinflips": [],
"posts": [
{
"title": "How to grow salad"
},
{
"title": "How to ride a horse"
}
]
}
결과
ts
{
"id": 1,
"name": null,
"email": "martina@prisma.io",
"profileViews": 0,
"role": "USER",
"coinflips": [],
"posts": [
{
"title": "How to grow salad"
},
{
"title": "How to ride a horse"
}
]
}

selectinclude는 같은 수준에서 사용할 수 없습니다. 즉, 사용자의 게시물을 include하고 각 게시물의 제목을 select하면, 사용자의 emailselect할 수 없습니다.

ts
// 다음 질의는 예외를 반환합니다.
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: { // 문제가 있습니다!
email: true
}
include: { // 문제가 있습니다!
posts: {
select: {
title: true
}
}
},
})
ts
// 다음 질의는 예외를 반환합니다.
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: { // 문제가 있습니다!
email: true
}
include: { // 문제가 있습니다!
posts: {
select: {
title: true
}
}
},
})
결과
text
Invalid `prisma.user.findUnique()` invocation:
{
where: {
id: 19
},
select: {
~~~~~~
email: true
},
include: {
~~~~~~~
posts: {
select: {
title: true
}
}
}
}
Please either use `include` or `select`, but not both at the same time.
결과
text
Invalid `prisma.user.findUnique()` invocation:
{
where: {
id: 19
},
select: {
~~~~~~
email: true
},
include: {
~~~~~~~
posts: {
select: {
title: true
}
}
}
}
Please either use `include` or `select`, but not both at the same time.

대신 중첩 select 옵션을 사용합니다.

ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: {
// 문제없습니다!
email: true,
posts: {
select: {
title: true,
},
},
},
})
ts
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: {
// 문제없습니다!
email: true,
posts: {
select: {
title: true,
},
},
},
})

관계 개수

3.0.1 이상에서는 필드와 함께 관계 개수를 include하거나 select할 수 있습니다. (예: 사용자의 게시물 수)

관계 목록 필터링하기

select를 사용하여 관련 레코드(예: 사용자의 게시물)에서 데이터의 하위 집합을 반환할 때, 해당 관계 목록을 필터링하고 정렬할 수 있습니다.

예를 들어 prisma.io 이메일 주소로 모든 사용자를 질의하고 게시된 게시물의 제목을 선택할 수 있습니다.

ts
const result = await prisma.user.findMany({
where: {
email: {
contains: 'prisma.io',
},
},
select: {
posts: {
where: {
published: false,
},
orderBy: {
title: 'asc',
},
select: {
title: true,
},
},
},
})
ts
const result = await prisma.user.findMany({
where: {
email: {
contains: 'prisma.io',
},
},
select: {
posts: {
where: {
published: false,
},
orderBy: {
title: 'asc',
},
select: {
title: true,
},
},
},
})

post 모델의 속성을 사용하여 동일한 질의를 작성할 수 있습니다.

ts
const result = await prisma.post.findMany({
where: {
published: false,
User: {
email: {
contains: 'prisma.io',
},
},
},
select: {
title: true,
},
})
ts
const result = await prisma.post.findMany({
where: {
published: false,
User: {
email: {
contains: 'prisma.io',
},
},
},
select: {
title: true,
},
})