メインコンテンツへスキップ

カスタムモデルとフィールド名

Prisma Client APIは、Prismaスキーマ内のモデルに基づいて生成されます。モデルは通常、データベーステーブルと1対1でマッピングされます。

場合によっては、特にイントロスペクションを使用する際に、データベースのテーブルやカラムの命名を、Prisma Client APIで使用される名前から分離することが役立つ場合があります。これは、Prismaスキーマ内の@mapおよび@@map属性を介して行うことができます。

@mapおよび@@mapを使用して、MongoDBのフィールドとコレクションをそれぞれ名前変更できます。このページではリレーショナルデータベースの例を使用しています。

例: リレーショナルデータベース

PostgreSQLリレーショナルデータベーススキーマが以下のように見えると仮定します。

CREATE TABLE users (
user_id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(256),
email VARCHAR(256) UNIQUE NOT NULL
);
CREATE TABLE posts (
post_id SERIAL PRIMARY KEY NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
title VARCHAR(256) NOT NULL,
content TEXT,
author_id INTEGER REFERENCES users(user_id)
);
CREATE TABLE profiles (
profile_id SERIAL PRIMARY KEY NOT NULL,
bio TEXT,
user_id INTEGER NOT NULL UNIQUE REFERENCES users(user_id)
);
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(256)
);
CREATE TABLE post_in_categories (
post_id INTEGER NOT NULL REFERENCES posts(post_id),
category_id INTEGER NOT NULL REFERENCES categories(category_id)
);
CREATE UNIQUE INDEX post_id_category_id_unique ON post_in_categories(post_id int4_ops,category_id int4_ops);

そのスキーマを持つデータベースをイントロスペクトすると、Prismaスキーマは以下のように表示されます。

model categories {
category_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
post_in_categories post_in_categories[]
}

model post_in_categories {
post_id Int
category_id Int
categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction)
posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
}

model posts {
post_id Int @id @default(autoincrement())
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories post_in_categories[]
}

model profiles {
profile_id Int @id @default(autoincrement())
bio String?
user_id Int @unique
users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
}

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

Prisma Client APIが生成される際、このPrismaスキーマにはいくつかの「問題」があります。

Prisma ORMの命名規則への準拠

Prisma ORMには、Prismaモデルに対してcamelCasing単数形を使用するという命名規則があります。これらの命名規則が守られない場合、Prismaスキーマの解釈が難しくなり、生成されるPrisma Client APIが不自然に感じられることがあります。以下の生成されたモデルを検討してください。

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

profilesは1:1のリレーションを参照していますが、その型は現在複数形のprofilesと呼ばれており、このリレーションには多くのprofilesが存在する可能性があることを示唆しています。Prisma ORMの慣習では、モデルとフィールドは理想的には次のように命名されます。

model User {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts Post[]
profile Profile?
}

これらのフィールドは「Prisma ORMレベル」のリレーションフィールドであり、実際に現れるわけではないため、Prismaスキーマで手動で名前を変更できます。

注釈付きリレーションフィールドの命名

外部キーは、Prismaスキーマ内の注釈付きリレーションフィールドと、それに対応するリレーションスカラーフィールドの組み合わせとして表現されます。SQLスキーマのすべてのリレーションは現在、次のように表現されています。

model categories {
category_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
post_in_categories post_in_categories[] // virtual relation field
}

model post_in_categories {
post_id Int // relation scalar field
category_id Int // relation scalar field
categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction) // virtual relation field
posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
}

model posts {
post_id Int @id @default(autoincrement())
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories post_in_categories[]
}

model profiles {
profile_id Int @id @default(autoincrement())
bio String?
user_id Int @unique
users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
}

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

Prisma Client APIでフィールドとモデルの名前を変更するために@map@@mapを使用する

@mapおよび@@map属性を使用して、Prisma Clientで使われるフィールドやモデルをデータベース内の「元の」名前にマッピングすることで、「名前を変更」できます。上記の例では、例えばモデルを次のように注釈付けすることができます。

prisma db pullでデータベースをイントロスペクトした、結果のPrismaスキーマを手動で次のように調整できます。

model Category {
id Int @id @default(autoincrement()) @map("category_id")
name String? @db.VarChar(256)
post_in_categories PostInCategories[]

@@map("categories")
}

model PostInCategories {
post_id Int
category_id Int
categories Category @relation(fields: [category_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
posts Post @relation(fields: [post_id], references: [id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
@@map("post_in_categories")
}

model Post {
id Int @id @default(autoincrement()) @map("post_id")
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users User? @relation(fields: [author_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories PostInCategories[]

@@map("posts")
}

model Profile {
id Int @id @default(autoincrement()) @map("profile_id")
bio String?
user_id Int @unique
users User @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)

@@map("profiles")
}

model User {
id Int @id @default(autoincrement()) @map("user_id")
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts Post[]
profiles Profile?

@@map("users")
}

これらの変更により、Prisma ORMの命名規則に準拠し、生成されたPrisma Client APIがより「自然」に感じられるようになります。

// Nested writes
const profile = await prisma.profile.create({
data: {
bio: 'Hello World',
users: {
create: {
name: 'Alice',
email: 'alice@prisma.io',
},
},
},
})

// Fluent API
const userByProfile = await prisma.profile
.findUnique({
where: { id: 1 },
})
.users()
情報

prisma db pullは、データベースを再イントロスペクトする際に、Prismaスキーマで@mapおよび@@mapを介して定義したカスタム名を保持します。

リレーションフィールドの名前変更

Prisma ORMレベルのリレーションフィールド(「仮想リレーションフィールド」と呼ばれることもあります)はPrismaスキーマにのみ存在し、基盤となるデータベースには実際には現れません。したがって、これらのフィールドには好きな名前を付けることができます。

SQLデータベースにおける曖昧なリレーションの以下の例を検討してください。

CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"author" integer NOT NULL,
"favoritedBy" INTEGER,
FOREIGN KEY ("author") REFERENCES "User"(id),
FOREIGN KEY ("favoritedBy") REFERENCES "User"(id)
);

Prisma ORMのイントロスペクションは、以下のPrismaスキーマを出力します。

model Post {
id Int @id @default(autoincrement())
author Int
favoritedBy Int?
User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
Post_Post_authorToUser Post[] @relation("Post_authorToUser")
Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser")
}

仮想リレーションフィールドPost_Post_authorToUserおよびPost_Post_favoritedByToUserの名前は生成されたリレーション名に基づいているため、Prisma Client APIではあまり分かりやすいものではありません。この場合、リレーションフィールドの名前を変更できます。例:

model Post {
id Int @id @default(autoincrement())
author Int
favoritedBy Int?
User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
writtenPosts Post[] @relation("Post_authorToUser")
favoritedPosts Post[] @relation("Post_favoritedByToUser")
}
情報

prisma db pullは、データベースを再イントロスペクトする際に、Prismaスキーマで定義されたカスタムリレーションフィールドを保持します。

© . All rights reserved.