Prisma2を触ってみた(メモ)


基本的には公式ドキュメントに書いてある

Prisma - Next-generation ORM for Node.js and TypeScript

そもそもPrismaとは何か

基本的なコンセプトはここに書いてある。

What is Prisma?

以下抜粋

Prisma is an open source next- generation ORM. It consists of the following parts:

  • Prisma Client: Auto-generated and type-safe query builder for Node.js & TypeScript
  • Prisma Migrate (experimental): Declarative data modeling & migration system
  • Prisma Studio: GUI to view and edit data in your database

つまりPrismaはORM, マイグレーション機構、GUIクライアントを内包したツール。

インストールしたもの

Express + TypeScript + MySQL + Docker

で素振りした。

Prismaを使うのに必要だったのは以下の2点

  • @prisma/client
  • @prisma/cli

導入の仕方

基本的には公式ドキュメントのチュートリアルをやるのが一番理解が早い。

Add Prisma to an existing project (15 min)

自前のDockerで立てたMySQLに繋ぐ場合、prisma/.envには

HOST = 'http://127.0.0.1'
MYSQL_DATABASE = 'prisma_practice'
MYSQL_USER = 'root'
MYSQL_PASSWORD = 'password'
MYSQL_ROOT_PASSWORD = 'password'

としていた場合は

DATABASE_URL = "mysql://root:[email protected]:3306/prisma_practice?schema=public"

こんな感じになる。

使い方

基本的な流れとしては

  • prisma/schema.prismaにprisma向けのデータモデルを記述して
prisma migrate save --experimental
prisma migrate up --experimental

を実行する。(schema.prismaはあくまでprismaにモデルを伝えるだけでこのファイルを変更しただけではDBには反映されない。なのでマイグレーションを行う。ただし--experimentalをつけている通りまだ安定版ではない)

  • このままでは@prisma/clientで参照しているschema.prismaが最新版になっていないため補完が効かない。なので
$ npx prisma generate

を実行する。

自分は最後のコマンドを叩くのを知らず、スキーマを変更した後で補完が効かず焦った。

ドキュメントはしっかり読みましょう・・・。

リレーションの作成

Relations (Reference)

ここに全て書いてある。(丸投げ感)

Explicit many-to-many relationsを作成した時

model User {
  id      Int      @id @default(autoincrement())
  name    String?
  email   String   @unique
  age     Int
  posts   Post[]
  Profile Profile?
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  createdAt DateTime @default(now())
  content   String?
  published Boolean  @default(false)
  thumbnail String?
  authorId  Int
  TagsOnPosts      TagsOnPosts[]
  author    User     @relation(fields: [authorId], references: [id])

  @@index([authorId], name: "authorId")
}

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

model Tag {
  id     Int     @id @default(autoincrement())
  name   String
  TagsOnPosts  TagsOnPosts[]
}

model TagsOnPosts {
  post        Post @relation(fields: [postId], references: [id])
  postId      Int
  tag         Tag  @relation(fields: [tagId], references: [id])
  tagId       Int
  
  @@id([postId, tagId])
}

schema.prismaがこの時

const post = await this.prisma.post.findOne({
  where: { id: Number(id) },
  include: {
    author: true,
    TagsOnPosts: {
      include: {
        tag: true
      }
    }
  }
})

多対多のリレーションを作成した時のデータの取得する時のコード。(中間テーブルを実装)
こんな感じでかけばpostに紐づいているタグも取得できる。

Explicit many-to-many relationsはいつ使うべきか?

ここに書いてある。

https://www.prisma.io/docs/concepts/components/prisma-schema/relations#many-to-many-relations

When you don't need to attach additional information to the relation, you can model m-n-relations as implicit many-to-many relations. If you're not using Prisma Migrate but obtain your data model from introspection, you can still make use of implicit many-to-many relations by following Prisma's conventions for relation tables.

つまり中間テーブルになんらかの追加情報(created_atとかがわかりやすい)を保存する場合はExplicit many-to-many relationsを使うと思われる。

最後に

すごい雑な記事でごめんなさい。

自分もまだ理解が追いついていないので間違った部分などございましたらコメントで指摘して頂けると助かります。