目前正在开发一个项目,以通过 Nestjs 进一步了解 prisma。但无法让架构发挥作用。种子不会通过,因为公寓取决于所有者字段,只能由创建的用户填充。
我想创建一个简单的数据库设置,其中用户可以是公寓的所有者,但必须拥有公寓。
一套公寓需要有一个业主,并且可以有多个租户。
非常感谢您在这里伸出援手,否则这只是另一个永远无法克服概念的项目。
架构:
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: '[email protected]',
password: hash,
flat: {
create: {
name: 'Test Flat',
owner: {
connect: {
users,
},
},
},
},
},
});
我会开始考虑关系。
额外要求是:
owner
公寓仍然是可选的您可以在您的
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 DEFERRED
或 DEFERRABLE 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});`;
});
目前需要在您的
previewFeatures = ["interactiveTransactions"]
中使用 schema.prisma
。
但在走这条路之前,我建议仔细检查您的应用程序将如何真正使用数据库。用户和单位是否总是在同一步骤中创建?