我在一个项目中使用了Prisma和PostgreSQL来存储和管理食谱.
我正在努力实现一个多对多关系,在这种关系中,我可以约束一方至少需要一个关系字段的值.
食谱可以有一种或多种香味.香气可以包含在零个或多个食谱中.
我使用一个显式关系表,因为我需要在其中存储额外的数据(食谱中每种香味的数量).
配方、香味和关系模型如下:
model Recipe {
id Int @id @default(autoincrement())
name String
base String? @default("50\/50")
description String? @default("aucune description")
rating Int? @default(1)
aromas RecipeToAromas[]
}
model Aroma {
id Int @id @default(autoincrement())
name String
brand Brand? @relation(fields: [brandId], references: [id])
brandId Int? @default(1)
recipes RecipeToAromas[]
@@unique([name, brandId], name: "aromaIdentifier")
}
model RecipeToAromas {
id Int @id @default(autoincrement())
recipeId Int
aromaId Int
quantityMl Int
recipe Recipe @relation(fields: [recipeId], references: [id])
aroma Aroma @relation(fields: [aromaId], references: [id])
}
我想限制食谱至少有一种香味.
根据定义,多对多定义了zero对多关系.
我考虑过在食谱和香味之间增加一个"一对多"的关系来解决这个问题.
这意味着在食谱中添加额外的香气字段来存储所需的香气(并将香气字段重命名为additional Aromas以避免混淆):
model Recipe {
id Int @id @default(autoincrement())
name String
base String? @default("50\/50")
description String? @default("aucune description")
rating Int? @default(1)
aromas RecipeToAromas[]
aroma Aroma @relation(fields: [aromaId], references: [id])
aromaId Int
}
以及根据需要在香气中添加配方字段以建立该关系:
model Aroma {
id Int @id @default(autoincrement())
name String
brand Brand? @relation(fields: [brandId], references: [id])
brandId Int? @default(1)
recipes RecipeToAromas[]
recipe Recipe[]
@@unique([name, brandId], name: "aromaIdentifier")
}
但这感觉不对,因为我将有重复:Aroma中的食谱和食谱字段将存储相同的数据.
* * 编辑** 我试图用这个解决方案解决问题,它产生了第二个问题: 食谱中的每种香味在这个食谱中都必须是唯一的(这可以通过关系数据库中的化合物@ unique反映出来).
如果我添加配方和香气之间的一对多关系,那么一个香气可以在一个配方中存储不止一次:
await prisma.recipe.create({
data: {
name: "First recipe",
aromaId: 1,
aromas: {
create: [
{ aromaId: 1, quantityMl: 2 },
{ aromaId: 2, quantityMl: 2 },
{ aromaId: 3, quantityMl: 2 },
],
},
},
});
当然,我可以通过依赖于Mutations 函数和用户输入的验证来解决这个问题.我可能会try 在类型上添加一层安全性,因为我正在使用typescript. 但我觉得这会使数据库变得脆弱,而且容易出错,特别是如果我不得不与其他开发人员合作,甚至在不同的项目中使用数据库.
我找不到任何涉及类似情况的资源,当然我花了很多时间搜索和重读文档.
我是新的prisma(昨天开始),我没有太多的经验与关系数据库,所以感觉我错过了一些东西.