prismaのクエリで1対多の「多に存在しないデータ」という条件で1を取り出す

ユーザー、お知らせ、ユーザーが既読したお知らせ、というデータ(テーブル)があり「ユーザーが既読していない全てのお知らせ」をprismaのクエリのみだけで取り出したい。

schema.prismaは以下

model User {
  id Int @id @default(autoincrement())
  name String
  readNotifications UserReadNotification[]
}

model Notification {
  id Int @id @default(autoincrement())
  title String
  text String
  alreadyRead UserReadNotification[]
}

model UserReadNotification {
  id Int @id @default(autoincrement())
  userId Int
  notificationId Int
  user User @relation(fields: [userId], references: [id])
  notification UserNotification @relation(fields: [notificationId], references: [id])
}

ソースコード

const prisma = new PrismaClient();
const userId = 1

const unreadData = await prisma.Notification.findMany({
    where: {
      alreadyRead: {
        none: { // noneを指定
          userId
        },
      },
    },
  });

noneはprismaの1:多の「多」からデータをフィルタリングするためのクエリ。 これをつけることで、指定したリレーション(ここではalreadyRead)の全てのデータの指定したカラム(ここではuserId)に指定したデータ(ここではuserId)が存在しなければそのデータを返す。ここではfindManyを使っているので条件を満たすデータを全て返す。 これで、「既読していない全てのお知らせ」言い換えると「UserReadNotificationのuserIdに指定したuserIdが存在しない全てのNotification」を取り出すことができる。

prismaのクエリ便利だな〜と思う。他にも「多」からデータをフィルタリングするためのクエリはある。

www.prisma.io

シンプルにするために実際に作ったコードを変更しているので、間違ったとこあったらごめんなさい。