メインコンテンツまでスキップ

include

findMany / findFirst でリレーション先のデータを一緒に取得したい場合に利用します。

使用するには事前にリレーション定義が必要です。

説明例用のシート

リレーション定義のシート例を使用します。

基本的な使い方

include にリレーション名を指定し、値に true を渡すと、リレーション先のデータが全て取得されます。

const result = gassma.Users.findMany({
include: {
posts: true,
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ id: 1, title: "初めての投稿", authorId: 1, published: true },
{ id: 2, title: "GASの使い方", authorId: 1, published: true },
],
},
{
id: 2,
name: "Bob",
email: "[email protected]",
posts: [
{ id: 3, title: "下書き記事", authorId: 2, published: false },
],
},
{
id: 3,
name: "Charlie",
email: "[email protected]",
posts: [],
},
];

リレーションの種類によって返される形が異なります。

リレーション種類返される形
oneToMany配列
manyToMany配列
oneToOne単一オブジェクト or null
manyToOne単一オブジェクト or null

manyToOne の例

const result = gassma.Posts.findMany({
include: {
author: true,
},
});

戻り値は以下の形式です。

[
{
id: 1,
title: "初めての投稿",
authorId: 1,
published: true,
author: { id: 1, name: "Alice", email: "[email protected]" },
},
{
id: 3,
title: "下書き記事",
authorId: 2,
published: false,
author: { id: 2, name: "Bob", email: "[email protected]" },
},
// ...
];

include のオプション

true の代わりにオブジェクトを渡すことで、リレーション先のデータに条件を付けることができます。

使用できるキー

キー名内容省略
whereリレーション先の取得条件
orderByリレーション先のソート
skipリレーション先のスキップ数
takeリレーション先の取得数
selectリレーション先の取得列の表示設定
omitリレーション先の取得列の除外設定
includeさらに深いリレーションの取得

where

リレーション先のデータに条件を付けて取得できます。

const result = gassma.Users.findMany({
include: {
posts: {
where: { published: true },
},
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ id: 1, title: "初めての投稿", authorId: 1, published: true },
{ id: 2, title: "GASの使い方", authorId: 1, published: true },
],
},
{
id: 2,
name: "Bob",
email: "[email protected]",
posts: [], // published: false の記事はフィルタされる
},
// ...
];

orderBy

リレーション先のデータをソートできます。

const result = gassma.Users.findMany({
include: {
posts: {
orderBy: { title: "desc" },
},
},
});

skip / take

リレーション先のデータをページネーションできます。skiptake を組み合わせて使用します。

const result = gassma.Users.findMany({
include: {
posts: {
orderBy: { id: "asc" },
skip: 1,
take: 1,
},
},
});

上記の例では、各ユーザーの投稿を id 昇順で並べ、最初の 1 件をスキップし、次の 1 件だけを取得します。

注記

skip / take は oneToMany と manyToMany で利用できます。oneToOne / manyToOne は単一レコードのため対象外です。

注意

includeskip / take に数値以外の値を渡すと IncludeInvalidOptionTypeError がスローされます。値によってメッセージが変わります。

gassma.Users.findMany({ include: { posts: { take: NaN } } });
// => IncludeInvalidOptionTypeError:
// Include "posts": option "take" must be a finite number

gassma.Users.findMany({ include: { posts: { take: null } } });
// => IncludeInvalidOptionTypeError:
// Include "posts": option "take" must be a number
メッセージ
NaN / Infinity / -Infinitymust be a finite number
null / 数値以外must be a number
undefined指定しなかった扱いになり無視されます

有限の負数はエラーになりません。take は末尾から取得し、skip に負数を渡した場合は GassmaSkipNegativeError になります。ネストした include のオプションも同じ検証を受けます。

select

リレーション先のデータの取得列を指定できます。

const result = gassma.Users.findMany({
include: {
posts: {
select: { title: true },
},
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ title: "初めての投稿" },
{ title: "GASの使い方" },
],
},
// ...
];

omit

リレーション先のデータの特定列を除外できます。

const result = gassma.Users.findMany({
include: {
posts: {
omit: { authorId: true },
},
},
});

omit はリレーション先モデルのグローバル omitとマージされます。トップレベルの omit と同様に、false を指定するとグローバル omit で除外されているフィールドをこの取得に限り再表示できます。

// グローバル omit で Posts.content を除外している場合
const result = gassma.Users.findMany({
include: {
posts: {
omit: { content: false }, // content が返る(グローバル omit を解除)
},
},
});
注意

selectomit は同時に指定できません。

ネストされた include

include の中にさらに include を指定することで、深い階層のリレーションを取得できます。

例えば、Users → Posts → Tags のようなリレーションを一度に取得できます。

const gassma = new Gassma.GassmaClient({
relations: {
Users: {
posts: {
type: "oneToMany",
to: "Posts",
field: "id",
reference: "authorId",
},
},
Posts: {
tags: {
type: "manyToMany",
to: "Tags",
field: "id",
reference: "id",
through: {
sheet: "PostTags",
field: "postId",
reference: "tagId",
},
},
},
},
});

const result = gassma.Users.findMany({
include: {
posts: {
include: {
tags: true,
},
},
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{
id: 1,
title: "初めての投稿",
authorId: 1,
published: true,
tags: [
{ id: 1, name: "GAS" },
{ id: 2, name: "JavaScript" },
],
},
{
id: 2,
title: "GASの使い方",
authorId: 1,
published: true,
tags: [
{ id: 1, name: "GAS" },
],
},
],
},
// ...
];
注意

selectinclude は同時に指定できません。

_count

リレーション先のレコード件数を取得できます。

全リレーションのカウント

_count: true を指定すると、定義されている全リレーションのレコード件数を取得します。

const result = gassma.Users.findMany({
include: {
_count: true,
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
_count: { posts: 2, profile: 1 },
},
{
id: 2,
name: "Bob",
email: "[email protected]",
_count: { posts: 1, profile: 0 },
},
// ...
];

特定リレーションのカウント

_count: { select: { ... } } でカウントするリレーションを指定できます。

const result = gassma.Users.findMany({
include: {
_count: {
select: { posts: true },
},
},
});

where フィルタ付きカウント

カウント対象に条件を付けることもできます。

const result = gassma.Users.findMany({
include: {
_count: {
select: {
posts: {
where: { published: true },
},
},
},
},
});

戻り値は以下の形式です。

[
{
id: 1,
name: "Alice",
email: "[email protected]",
_count: { posts: 2 }, // published: true の投稿のみカウント
},
// ...
];

select と _count の組み合わせ

トップレベルの select_count を組み合わせることもできます。

const result = gassma.Users.findMany({
select: {
name: true,
_count: {
select: { posts: true },
},
},
});

戻り値は以下の形式です。

[
{ name: "Alice", _count: { posts: 2 } },
{ name: "Bob", _count: { posts: 1 } },
// ...
];
注記

_count は全てのリレーション種別(oneToMany / oneToOne / manyToOne / manyToMany)に対応しています。

複数リレーションの同時取得

1 回のクエリで複数のリレーションを同時に取得できます。

const result = gassma.Users.findMany({
include: {
posts: true,
profile: true,
},
});

include と select の制限

トップレベルselectinclude は同時に使用できません。

// これはエラーになります
gassma.Users.findMany({
select: { name: true },
include: { posts: true },
});

バリデーション

エラー原因
IncludeWithoutRelationsErrorリレーション定義なしで include を使用
GassmaIncludeSelectConflictErrorトップレベルで includeselect を同時使用
IncludeSelectOmitConflictErrorinclude 内で selectomit を同時指定
IncludeSelectIncludeConflictErrorinclude 内で selectinclude を同時指定
IncludeInvalidOptionTypeErrorinclude の値やオプションの型が不正
GassmaRelationNotFoundError指定したリレーション名が定義されていない