[英]Seeding with prisma nested create with one-to-one relation
Currently working on a project to learn a bit more about prisma with nestjs.目前正在开展一个项目,以使用 nestjs 了解更多关于 prisma 的信息。 But cant get the schema to work.
但不能让架构工作。 The seed wont go through because the flat depends on the owner field, that can only be filled with the created user.
种子不会 go 通过,因为平面依赖于所有者字段,只能用创建的用户填充。
I wanted to create a simple database setup where a user can be an owner of a flat, but must have a flat.我想创建一个简单的数据库设置,其中用户可以是公寓的所有者,但必须拥有公寓。
A flat needs to have an owner, and can have multiple tennants.一个公寓需要有一个所有者,并且可以有多个租户。
Would be very thankful for a helpful hand here, otherwise its just another project that will never get over concepts.非常感谢这里的帮助,否则它只是另一个永远不会克服概念的项目。
Schema:架构:
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,
},
},
},
},
},
});
You will need to create the user
first and then connect
the flat
in a subsequent operation.您需要先创建
user
,然后在后续操作中connect
flat
。 I would wrap this in an interactive transaction .我会将其包装在交互式事务中。
I would start thinking in terms of relations.我会开始考虑关系。
Additional requirements are:附加要求是:
owner
of flat remains optionalowner
仍然是可选的You can model these relations like this in your schema.prisma
(simplified):您可以 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")
}
There is no need to introduce a redundant User.ownerOfId
.无需引入多余的
User.ownerOfId
。
That schema does not guarantee that each flat has an owner as ownerId
is optional.该模式不保证每个公寓都有一个所有者,因为
ownerId
是可选的。
If you accept this flaw, you can create user and flat like this:如果你接受这个缺陷,你可以像这样创建用户和平面:
await prisma.user.create({
data: { nickname: "flo", flat: { create: { name: "Test flat" } } },
});
and in a second step set the owner of the flat to the user...然后在第二步中将公寓的所有者设置为用户...
owner
of flat should be mandatoryowner
应该是强制性的If you do not accept this flaw, and make ownerId
non-optional, seeding becomes indeed more difficult as you are having a circular dependency.如果您不接受这个缺陷,并且将
ownerId
非可选,那么播种确实会变得更加困难,因为您有循环依赖。
In the schema, you just remove the two question marks:在架构中,您只需删除两个问号:
model Flat {
...
ownerId String @unique
owner User @relation(fields: [ownerId], references: [userId], name: "ownerRelation")
...
You would then have to:然后,您必须:
DEFERRABLE INITIALLY DEFERRED
or DEFERRABLE INITIALLY IMMEDIATE
on your database.DEFERRABLE INITIALLY DEFERRED
或DEFERRABLE INITIALLY IMMEDIATE
。 Currently, prisma cannot do that (see: 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});`;
});
which currently requires previewFeatures = ["interactiveTransactions"]
in your schema.prisma
.目前需要在您的
schema.prisma
中使用previewFeatures = ["interactiveTransactions"]
。
But before going down that route, I'd suggest to double check how your app would really use the database.但在走这条路之前,我建议仔细检查您的应用程序将如何真正使用数据库。 Would user and flat always be created in the same step?
用户和平面是否总是在同一步骤中创建?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.