簡體   English   中英

使用具有一對一關系的 prisma 嵌套創建播種

[英]Seeding with prisma nested create with one-to-one relation

目前正在開展一個項目,以使用 nestjs 了解更多關於 prisma 的信息。 但不能讓架構工作。 種子不會 go 通過,因為平面依賴於所有者字段,只能用創建的用戶填充。

我想創建一個簡單的數據庫設置,其中用戶可以是公寓的所有者,但必須擁有公寓。

一個公寓需要有一個所有者,並且可以有多個租戶。

非常感謝這里的幫助,否則它只是另一個永遠不會克服概念的項目。

架構:

model User {
  userId        String    @id @default(uuid())
  firstName     String?
  lastName      String?
  nickname      String
  email         String    @unique
  password      String
  phoneNumber   String?
  ownerOf       Flat?     @relation("owner")
  ownerOfId     String?   @unique
  flatId        String
  flat          Flat      @relation(fields: [flatId], references: [flatId])
  paidFor    Expense[] @relation("paidBy")
  otherExpenses Expense[]
  updatedAt     DateTime? @updatedAt
  createdAt     DateTime? @default(now())

  @@map("users")
}

model Flat {
  flatId    String    @id @default(uuid())
  name      String
  owner     User?      @relation("owner", fields: [ownerId], references: [userId])
  ownerId   String?    @unique
  flatmates User[]
  expenses  Expense[]
  updatedAt DateTime? @updatedAt
  createdAt DateTime? @default(now())

  @@map("flats")
}

model Expense {
  expenseId   String    @id @default(uuid())
  flatId      String
  flat        Flat      @relation(fields: [flatId], references: [flatId])
  paidBy   User      @relation("paidBy", fields: [paidById], references: [userId])
  paidById String
  expenseFor  User[]
  amount      Float
  updatedAt   DateTime? @updatedAt
  createdAt   DateTime? @default(now())

  @@map("expenses")
}
const users = await prisma.user.create({
    data: {
      firstName: 'Flo',
      lastName: 'Test',
      nickname: 'flo',
      email: 'test@test.de',
      password: hash,
      flat: {
        create: {
          name: 'Test Flat',
          owner: {
            connect: {
              users,
            },
          },
        },
      },
    },
  });

您需要先創建user ,然后在后續操作中connect flat 我會將其包裝在交互式事務中。

我會開始考慮關系。

  • 公寓與租戶之間的關系是什么? 現在是 1:n。 一套公寓可以有多個租戶。 一個用戶只能是一個單位的租戶。
  • 公寓和業主之間是什么關系? 從您的架構來看,它是 1:1。 (您可能需要仔細檢查。用戶不能擁有多個公寓嗎?)

附加要求是:

  • 用戶必須是公寓的租戶。
  • 公寓必須有所有者(來自您的問題文本)。 但是您的架構不需要那樣。 這是一個關鍵點。

單位的owner仍然是可選的

您可以 model 這些關系在您的schema.prisma (簡化)中像這樣:

model User {
  userId    String @id @default(uuid())
  nickname  String
  flatId    String
  flat      Flat   @relation(fields: [flatId], references: [flatId], name: "tenantRelation")
  ownedFlat Flat?  @relation(name: "ownerRelation")

  @@map("users")
}

model Flat {
  flatId  String  @id @default(uuid())
  name    String
  ownerId String? @unique
  owner   User?   @relation(fields: [ownerId], references: [userId], name: "ownerRelation")
  tenants User[]  @relation(name: "tenantRelation")

  @@map("flats")
}

無需引入多余的User.ownerOfId

該模式不保證每個公寓都有一個所有者,因為ownerId是可選的。

如果你接受這個缺陷,你可以像這樣創建用戶和平面:

await prisma.user.create({
  data: { nickname: "flo", flat: { create: { name: "Test flat" } } },
});

然后在第二步中將公寓的所有者設置為用戶...

公寓owner應該是強制性的

如果您不接受這個缺陷,並且將ownerId非可選,那么播種確實會變得更加困難,因為您有循環依賴。

在架構中,您只需刪除兩個問號:

model Flat {
  ...
  ownerId String @unique
  owner   User   @relation(fields: [ownerId], references: [userId], name: "ownerRelation")
  ...

然后,您必須:

  • 在數據庫上設置外鍵DEFERRABLE INITIALLY DEFERREDDEFERRABLE INITIALLY IMMEDIATE 目前,prisma 無法做到這一點(參見: https://github.com/prisma/prisma/issues/8807 )。
  • 在同一個事務中執行原始查詢,如下所示:
import { v4 as uuidv4 } from "uuid";

// ...

  const userId = uuidv4();
  const flatId = uuidv4();

  await prisma.$transaction(async ($tx) => {
    await $tx.$executeRaw`set constraints all deferred;`;
    await $tx.$executeRaw`INSERT INTO users ("userId", "nickname", "flatId") VALUES (${userId}, 'flo', ${flatId});`;
    await $tx.$executeRaw`INSERT INTO flats ("flatId", "name", "ownerId") VALUES (${flatId}, 'Test flat', ${userId});`;
  });

目前需要在您的schema.prisma中使用previewFeatures = ["interactiveTransactions"]

但在走這條路之前,我建議仔細檢查您的應用程序將如何真正使用數據庫。 用戶和平面是否總是在同一步驟中創建?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM