おひさしどうもてぃです。
最近は個人開発で自分のshopだったりhomeブログだったり作っていて、あまり記事をアウトプットできてなかったので書きます。
いつも通り解決シリーズです。
環境
- NestJS 8.0.0
- Prisma client 4.0.0
NestJS × Prisma × GraphQLの構成です。
問題
Prismaのupsertで要求されるwhereの型にidしか表示されず、他の条件(たとえばemailとか)を入れたとしてもエラーを返されていました。
該当のコードはこちら。
import { Injectable } from '@nestjs/common' import { Prisma, User } from '@prisma/client' import { PrismaService } from '~/prisma/prisma.service' @Injectable() export class UsersService { constructor(private readonly prisma: PrismaService) {} // auth validateで使用 async findOrCreateBy(email: string): Promise<User> { return await this.prisma.user.upsert({ where: { email: email }, update: { email: email }, create: { email: email, name: 'test user' }, }) } }
ちな、Prisma公式を参考にしました。
上のままだと型のエラーが出ていたのでupsertの定義元の型を確認してみました。
すると…
/** * User upsert */ export type UserUpsertArgs = { /** * Select specific fields to fetch from the User * **/ select?: UserSelect | null /** * Choose, which related nodes to fetch as well. * **/ include?: UserInclude | null /** * The filter to search for the User to update in case it exists. * **/ where: UserWhereUniqueInput /** * In case the User found by the `where` argument doesn't exist, create a new User with this data. * **/ create: XOR<UserCreateInput, UserUncheckedCreateInput> /** * In case the User was found with the provided `where` argument, update it with this data. * **/ update: XOR<UserUpdateInput, UserUncheckedUpdateInput> } . . . export type UserWhereUniqueInput = { id?: string }
upsertのwhereに使われているのは UserWhereUniqueInput
で、この子を確認してみるとidしか型にない…
どういうこと!?
公式をもっとちゃんと見ましょう
そういうこと。
Upsertのところをもっとちゃんと見てみましょう。
↑のwhereのところに注目。
Wraps all unique fields of a model so that individual records can be selected
unique field
、これだわ。
もっとわかりやっすく書いてほしい…(切実)、せめて大文字とか。
解決
ということで、prisma.schemaにunique制約をかけて…
// User(ユーザー) model User { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid email String? @unique() @default("") phoneNumber String? @unique() @default("") @map("phone_number") companyName String? @default("") @map("company_name") address String? @default("") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6) }
マイグレーションをかければ
$ npx prisma migrate dev --name add_unique --skip-seed
UserWhereUniqueInput
がこんな感じになりました。
export type UserWhereUniqueInput = { id?: string email?: string phoneNumber?: string }
ちゃんとUnique制約つけたカラムが追加されてました。