Skip to main content

include

Used to retrieve related data together with findMany / findFirst.

Requires a prior relation definition.

Example Sheets

Uses the sheet examples from relation definition.

Basic Usage

Specify a relation name in include with a value of true to retrieve all related data.

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

The return value has the following format:

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ id: 1, title: "First Post", authorId: 1, published: true },
{ id: 2, title: "How to use GAS", authorId: 1, published: true },
],
},
{
id: 2,
name: "Bob",
email: "[email protected]",
posts: [
{ id: 3, title: "Draft Article", authorId: 2, published: false },
],
},
{
id: 3,
name: "Charlie",
email: "[email protected]",
posts: [],
},
];

The returned shape differs by relation type:

Relation TypeReturned Shape
oneToManyArray
manyToManyArray
oneToOneSingle object or null
manyToOneSingle object or null

manyToOne Example

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

The return value has the following format:

[
{
id: 1,
title: "First Post",
authorId: 1,
published: true,
author: { id: 1, name: "Alice", email: "[email protected]" },
},
{
id: 3,
title: "Draft Article",
authorId: 2,
published: false,
author: { id: 2, name: "Bob", email: "[email protected]" },
},
// ...
];

include Options

Instead of true, you can pass an object to apply conditions to the related data.

Available Keys

KeyDescriptionOptional
whereQuery conditions for related dataOptional
orderBySort order for related dataOptional
skipNumber of related records to skipOptional
takeNumber of related records to retrieveOptional
selectDisplay settings for related columnsOptional
omitExclusion settings for related columnsOptional
includeRetrieve deeper nested relationsOptional

where

Apply conditions to filter related data:

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

The return value has the following format:

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ id: 1, title: "First Post", authorId: 1, published: true },
{ id: 2, title: "How to use GAS", authorId: 1, published: true },
],
},
{
id: 2,
name: "Bob",
email: "[email protected]",
posts: [], // published: false articles are filtered out
},
// ...
];

orderBy

Sort related data:

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

skip / take

Paginate related data using skip and take together:

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

The above example orders each user's posts by id ascending, skips the first one, and retrieves only the next one.

note

skip / take are available for oneToMany and manyToMany. They are not applicable to oneToOne / manyToOne as they return a single record.

caution

Passing a non-number to skip / take in include throws an IncludeInvalidOptionTypeError. The message differs depending on the value.

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
ValueMessage
NaN / Infinity / -Infinitymust be a finite number
null or any non-numbermust be a number
undefinedTreated as "not specified" and ignored

Finite negative numbers are not errors: take reads from the end, and a negative skip throws GassmaSkipNegativeError. Options of nested include receive the same validation.

select

Specify which columns to retrieve from related data:

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

The return value has the following format:

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{ title: "First Post" },
{ title: "How to use GAS" },
],
},
// ...
];

omit

Exclude specific columns from related data:

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

omit is merged with the related model's global omit. As with the top-level omit, specifying false re-includes a field hidden by the global omit for this fetch only:

// With a global omit excluding Posts.content
const result = gassma.Users.findMany({
include: {
posts: {
omit: { content: false }, // content is returned (overrides the global omit)
},
},
});
caution

select and omit cannot be specified simultaneously.

Nested include

You can specify include within include to retrieve deep relation hierarchies.

For example, you can retrieve Users → Posts → Tags in a single query:

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,
},
},
},
});

The return value has the following format:

[
{
id: 1,
name: "Alice",
email: "[email protected]",
posts: [
{
id: 1,
title: "First Post",
authorId: 1,
published: true,
tags: [
{ id: 1, name: "GAS" },
{ id: 2, name: "JavaScript" },
],
},
{
id: 2,
title: "How to use GAS",
authorId: 1,
published: true,
tags: [
{ id: 1, name: "GAS" },
],
},
],
},
// ...
];
caution

select and include cannot be specified simultaneously.

_count

Retrieve the count of related records.

Count All Relations

Specify _count: true to get the record count for all defined relations:

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

The return value has the following format:

[
{
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 Specific Relations

Use _count: { select: { ... } } to specify which relations to count:

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

Count with where Filter

You can also add conditions to the count target:

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

The return value has the following format:

[
{
id: 1,
name: "Alice",
email: "[email protected]",
_count: { posts: 2 }, // Only published: true posts are counted
},
// ...
];

Combining select and _count

You can combine top-level select with _count:

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

The return value has the following format:

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

_count supports all relation types (oneToMany / oneToOne / manyToOne / manyToMany).

Retrieving Multiple Relations Simultaneously

You can retrieve multiple relations in a single query:

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

Restrictions on include and select

Top-level select and include cannot be used simultaneously.

// This will throw an error
gassma.Users.findMany({
select: { name: true },
include: { posts: true },
});

Validation

ErrorCause
IncludeWithoutRelationsErrorUsed include without relation definitions
GassmaIncludeSelectConflictErrorUsed include and select simultaneously at the top level
IncludeSelectOmitConflictErrorUsed select and omit simultaneously within include
IncludeSelectIncludeConflictErrorUsed select and include simultaneously within include
IncludeInvalidOptionTypeErrorInvalid type for include value or option
GassmaRelationNotFoundErrorSpecified relation name is not defined