m_shige1979のときどきITブログ

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

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

https://github.com/mshige1979

PrismaでDBのhasOneを試す

Prisma

www.prisma.io

hasOneについて

2つのテーブルが1対1、または0の関係のリレーショナル構造のこと

イメージ

f:id:m_shige1979:20211123095306p:plain

Prismaでの定義の方法

prisma/schema.prisma

// ユーザーデータ管理用
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?

  // テーブルの物理名
  @@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")
}

親モデルへの追加定義

  // プロフィール(One to One)
  profile Profile?

これを追加することで関連するモデルが1または0の状態となる

子モデルへの追加定義

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

紐付け用のカラムを追加し親と関連づける

マイグレーション後の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=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

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

データ処理

親のみ取得

    const user1 = await prisma.user.findFirst({
        where: {
            name: 'hoge1'
        },
    })    
    console.log("case1: ", user1)

親子のデータを同時に取得

    const user2 = await prisma.user.findFirst({
        where: {
            name: 'hoge1'
        },
        include: {
            profile: true,
        },
    })    
    console.log("case2: ", user2)

子のデータを一部のみ取得

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

子のデータより親を引き出す

    const profile1 = prisma.profile.findFirst({
        where: {
            nickName: 'aaaa'
        },
    });
    const user4 = await profile1.user();
    profile1.then((result) => {
        console.log("case4: ", result, user4);
    })

case1:  {
  id: 10,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T01:14:46.450Z,
  updatedAt: 2021-11-23T01:14:46.450Z
}
case2:  {
  id: 10,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T01:14:46.450Z,
  updatedAt: 2021-11-23T01:14:46.450Z,
  profile: {
    id: 3,
    nickName: 'aaaa',
    createdAt: 2021-11-23T01:14:46.450Z,
    updatedAt: 2021-11-23T01:14:46.450Z,
    userId: 10
  }
}
case3:  {
  id: 10,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T01:14:46.450Z,
  updatedAt: 2021-11-23T01:14:46.450Z,
  profile: { nickName: 'aaaa', createdAt: 2021-11-23T01:14:46.450Z }
}
case4:  {
  id: 3,
  nickName: 'aaaa',
  createdAt: 2021-11-23T01:14:46.450Z,
  updatedAt: 2021-11-23T01:14:46.450Z,
  userId: 10
} {
  id: 10,
  email: 'hoge1@example.com',
  name: 'hoge1',
  age: 20,
  createdAt: 2021-11-23T01:14:46.450Z,
  updatedAt: 2021-11-23T01:14:46.450Z
}

親だけ削除とかはできんかった

多分、リレーションの設定で削除も連動するようにしてないせいと思うが seedファイルを改修する際に、削除⇨作成したらエラーになる。 ちょっと気をつけよう

できたやつ

github.com

参考

Relation queries (Concepts) | Prisma Docs