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

JavaScriptプロジェクトにおけるCockroachDBのイントロスペクション

Prisma ORMでデータベースをイントロスペクトする

このガイドでは、3つのテーブルを持つデモSQLスキーマを使用します

CREATE TABLE "User" (
id INT8 PRIMARY KEY DEFAULT unique_rowid(),
name STRING(255),
email STRING(255) UNIQUE NOT NULL
);

CREATE TABLE "Post" (
id INT8 PRIMARY KEY DEFAULT unique_rowid(),
title STRING(255) UNIQUE NOT NULL,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
content STRING,
published BOOLEAN NOT NULL DEFAULT false,
"authorId" INT8 NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "User"(id)
);

CREATE TABLE "Profile" (
id INT8 PRIMARY KEY DEFAULT unique_rowid(),
bio STRING,
"userId" INT8 UNIQUE NOT NULL,
FOREIGN KEY ("userId") REFERENCES "User"(id)
);

注意: CockroachDBが適切な大文字・小文字を区別して使用するように、一部のフィールドは二重引用符で囲まれています。二重引用符が使用されていない場合、CockroachDBはすべてを小文字として読み取ります。

テーブルのグラフィカルな概要を展開

User

列名主キー外部キー必須デフォルト
idINT8✔️いいえ✔️自動インクリメント
nameSTRING(255)いいえいいえいいえ-
emailSTRING(255)いいえいいえ✔️-

Post

列名主キー外部キー必須デフォルト
idINT8✔️いいえ✔️自動インクリメント
createdAtTIMESTAMPいいえいいえ✔️now()
titleSTRING(255)いいえいいえ✔️-
contentSTRINGいいえいいえいいえ-
publishedBOOLEANいいえいいえ✔️false
authorIdINT8いいえ✔️✔️-

Profile

列名主キー外部キー必須デフォルト
idINT8✔️いいえ✔️自動インクリメント
bioSTRINGいいえいいえいいえ-
userIdINT8いいえ✔️✔️-

次のステップとして、データベースをイントロスペクトします。イントロスペクションの結果は、Prismaスキーマ内のデータモデルになります。

データベースをイントロスペクトするには、次のコマンドを実行します

npx prisma db pull

このコマンドは、schema.prisma内でurlを定義するために使用される環境変数DATABASE_URL(この場合は.envに設定されています)を読み取り、データベースに接続します。接続が確立されると、データベースをイントロスペクトし(つまり、データベーススキーマを読み取ります)、その後、データベーススキーマをSQLからPrismaデータモデルに変換します。

イントロスペクションが完了すると、Prismaスキーマが更新されます

Introspect your database

データモデルは次のようになります

prisma/schema.prisma
model Post {
id BigInt @id @default(autoincrement())
title String @unique @db.String(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId BigInt
User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model Profile {
id BigInt @id @default(autoincrement())
bio String?
userId BigInt @unique
User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id BigInt @id @default(autoincrement())
name String? @db.String(255)
email String @unique @db.String(255)
Post Post[]
Profile Profile?
}

Prisma ORMのデータモデルは、データベーススキーマを宣言的に表現したものであり、生成されたPrisma Clientライブラリの基盤となります。Prisma Clientインスタンスは、これらのモデルに合わせて調整されたクエリを公開します。

現在、データモデルにはいくつかの小さな「問題」があります

  • Userリレーションフィールドは大文字で記述されており、Prismaの命名規則に準拠していません。より多くの「セマンティクス」を表現するために、このフィールドをauthorと呼んでUserPost間の関係をより良く記述するのが望ましいでしょう。
  • User上のPostおよびProfileリレーションフィールド、ならびにProfile上のUserリレーションフィールドはすべて大文字で記述されています。Prismaの命名規則に準拠するには、これら両方のフィールドをpostprofileuserと小文字にする必要があります。
  • 小文字にしても、User上のpostフィールドはまだ少し名前が不適切です。これは、実際には投稿のリストを指しているためです。したがって、より良い名前は複数形であるpostsでしょう。

これらの変更は、生成されたPrisma Client APIにとって重要です。authorpostsprofileuserといった小文字のリレーションフィールドを使用することで、JavaScript/TypeScript開発者にとってより自然で慣用的なものに感じられるでしょう。したがって、Prisma Client APIを設定できます。

リレーションフィールド仮想的である(つまり、データベースに直接現れない)ため、データベースに手を加えることなくPrismaスキーマで手動で名前を変更できます。

prisma/schema.prisma
model Post {
id BigInt @id @default(autoincrement())
title String @unique @db.String(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId BigInt
author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model Profile {
id BigInt @id @default(autoincrement())
bio String?
userId BigInt @unique
user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id BigInt @id @default(autoincrement())
name String? @db.String(255)
email String @unique @db.String(255)
posts Post[]
profile Profile?
}

この例では、データベーススキーマはPrisma ORMモデルの命名規則に従っていました(イントロスペクションから生成された仮想リレーションフィールドのみがそれらに準拠しておらず、調整が必要でした)。これにより、生成されるPrisma Client APIの人間工学が最適化されます。

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

しかし、Prisma Client APIで公開されるカラム名やテーブル名に追加の変更を加えたい場合があります。一般的な例としては、データベーススキーマでよく使用されるsnake_case表記を、JavaScript/TypeScript開発者にとってより自然に感じられるPascalCasecamelCase表記に変換することが挙げられます。

イントロスペクションから、snake_case表記に基づいた以下のモデルを取得したと仮定します

model my_user {
user_id Int @id @default(sequence())
first_name String?
last_name String @unique
}

このモデルのPrisma Client APIを生成した場合、そのAPIにはsnake_case表記が引き継がれます

const user = await prisma.my_user.create({
data: {
first_name: 'Alice',
last_name: 'Smith',
},
})

Prisma Client APIでデータベースのテーブル名やカラム名を使用しない場合は、@map@@mapで設定できます。

model MyUser {
userId Int @id @default(sequence()) @map("user_id")
firstName String? @map("first_name")
lastName String @unique @map("last_name")

@@map("my_user")
}

このアプローチにより、モデルとそのフィールドを自由に命名し、@map(フィールド名用)と@@map(モデル名用)を使用して、基になるテーブルとカラムを指すことができます。Prisma Client APIは次のようになります

const user = await prisma.myUser.create({
data: {
firstName: 'Alice',
lastName: 'Smith',
},
})

詳細については、Prisma Client APIの設定ページを参照してください。

© . All rights reserved.