はじめに
prismaでクエリを発行する際、passwordカラム等の除外したいカラムを
this.prisma.user.findUnique({
where: userWhereUniqueInput,
exclude: 'password'
})
と書けたらいいなぁ…という妄想を全人類がしていることだと思う。
これ、2020年4月からissueがあるのに、全く対応される気配がない。
愚直に select
で
this.prisma.user.findUnique({
where: userWhereUniqueInput,
select: { id: true, email: true, ... },
})
と書くこともできるのだが、これだとuserテーブルにカラムが増えるたびに
手動ですべての select
文をイジることになるのでつらい。
対応策
excludeしたいカラム以外のすべてのフィールドを列挙する関数を作り、
selectに指定してあげれば良い。
①以下関数を任意の場所に作成する
export const prismaExclude = <T extends Models['fields'], ExcludeT extends (keyof T)[]>(
fields: T,
exclude: ExcludeT,
) => {
const keys = Object.keys(fields) as (keyof T)[];
const excludeSet = new Set(exclude);
const attributes: Partial<Record<keyof T[][number], boolean>> = {};
for (const key of keys) {
if (excludeSet.has(key)) attributes[key] = false;
else attributes[key] = true;
}
type IncludeType = {
[K in keyof T]: true;
};
type Result = Omit<IncludeType, ExcludeT[number]>;
return attributes as Result;
};
②以下のように使う。prismaのfieldsを第一引数、除外したいカラムの配列を第二引数に渡す。
(例はfindUniqueだが、findMany, create, update, delete 等でも使える)
this.prisma.user.findUnique({
where: userWhereUniqueInput,
select: prismaExclude(this.prisma.user.fields, ['password'])
})
注意
fieldsはPrisma 4.3.0 からPreviewで入り、5.0.0で正式に取り入れられた機能なので、
- 4.3.0未満を使っている人 → 要アップデート
- 4.3.0以上~5.0.0未満を使っている人 → prisma.schemaに以下の記載が必要
generator client { provider = "prisma-client-js" output = "./client" previewFeatures = ["fieldReference"] // ★追記 }
あとがき
おそらくいつか公式でexcludeに対応する日が来ると思うので、
この記事がそれまでのつなぎになれば幸いだ。
ちなみにこの方法は上記issueに出てきたこれを参考にした