m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

PrismaでDBのhasOneを試す

前の記事

m-shige1979.hatenablog.com

今回

f:id:m_shige1979:20211123190202p:plain

外部キーの定義って

後付けや変更ができないのかな? 普段SQLを使うことが多かったので今回prisma migrate devでエラーでできないから分かっていない・・・

設定したもの

prisma/schema.prisma

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

// ER図作成用
generator erd {
  provider = "prisma-erd-generator"
  output   = "../doc/ERD.md"
}

// ユーザーデータ管理用
model User {
  // ID
  id    Int     @id @default(autoincrement())
  // メールアドレス
  email String  @unique
  // 氏名
  name  String?
  // 年齢
  age   Int?

  // 登録日時
  createdAt DateTime @default(now()) @map("created_at")
  // 更新日時
  updatedAt DateTime @default(now()) @map("updated_at")

  // プロフィール(One to One)
  profile Profile?
  // 記事(One to Many)
  posts   Post[]

  // テーブルの物理名
  @@map("users")
}

// プロフィール管理用
model Profile {
  // ID
  id       Int    @id @default(autoincrement())
  // ニックネーム
  nickName String @map("nick_name")

  // 登録日時
  createdAt DateTime @default(now()) @map("created_at")
  // 更新日時
  updatedAt DateTime @default(now()) @map("updated_at")

  // 親テーブルの関連づけ
  userId Int  @unique
  user   User @relation(fields: [userId], references: [id])

  // テーブルの物理名
  @@map("profile")
}

// 記事管理用
model Post {
  // ID
  id    Int    @id @default(autoincrement())
  // タイトル
  title String @map("title")
  // 登録日時
  createdAt DateTime @default(now()) @map("created_at")
  // 更新日時
  updatedAt DateTime @default(now()) @map("updated_at")
  
  // 親テーブルの関連づけ
  userId Int
  user   User @relation(fields: [userId], references: [id])

  // テーブルの物理名
  @@map("posts")
}

migrate後のCREATE文

CREATE TABLE `users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  `updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_key` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `posts` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  `updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  `userId` int NOT NULL,
  PRIMARY KEY (`id`),
  KEY `posts_userId_fkey` (`userId`),
  CONSTRAINT `posts_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

データ取得方法

基本は前回と同じ、今回は1対多のため、関連テーブルの条件絞り込みが可能

    const user3 = await prisma.user.findFirst({
        where: {
            name: 'hoge1'
        },
        include: {
            profile: {
                select: {
                    nickName: true,
                    createdAt: true,
                },
            },
            posts: {
                select: {
                    title: true
                },
                where: {
                    title: "test1"
                }
            }
        },
    })    
    console.log("case3: ", user3)

配下を全件取得した場合

  id: 16,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T09:58:03.729Z,
  updatedAt: 2021-11-23T09:58:03.729Z,
  profile: {
    id: 5,
    nickName: 'aaaa',
    createdAt: 2021-11-23T09:58:03.729Z,
    updatedAt: 2021-11-23T09:58:03.729Z,
    userId: 16
  },
  posts: [
    {
      id: 1,
      title: 'test1',
      createdAt: 2021-11-23T09:58:03.729Z,
      updatedAt: 2021-11-23T09:58:03.729Z,
      userId: 16
    },
    {
      id: 2,
      title: 'test2',
      createdAt: 2021-11-23T09:58:03.729Z,
      updatedAt: 2021-11-23T09:58:03.729Z,
      userId: 16
    },
    {
      id: 3,
      title: 'test3',
      createdAt: 2021-11-23T09:58:03.729Z,
      updatedAt: 2021-11-23T09:58:03.729Z,
      userId: 16
    }
  ]
}

一部のみ取得した場合

case3:  {
  id: 16,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T09:58:03.729Z,
  updatedAt: 2021-11-23T09:58:03.729Z,
  profile: { nickName: 'aaaa', createdAt: 2021-11-23T09:58:03.729Z },
  posts: [ { title: 'test1' } ]
}

所感

ある程度のことはやってくれるイメージ
外部キーのこともあるから頻繁にデータ構造が変わる場合や複雑なSQLがある場合は不向き
次は多対多group by辺りを見てみる

できたもの

github.com