[英]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
。 我会将其包装在交互式事务中。
我会开始考虑关系。
附加要求是:
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 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});`;
});
目前需要在您的schema.prisma
中使用previewFeatures = ["interactiveTransactions"]
。
但在走这条路之前,我建议仔细检查您的应用程序将如何真正使用数据库。 用户和平面是否总是在同一步骤中创建?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.