Prisma Schema 中的多态性 - 最佳实践?

buz*_*sin 5 nexus graphql prisma prisma-graphql nexus-prisma

这更像是一个设计问题,而不是一个编码问题。假设有以下架构:

// schema.prisma
// Solution 1

model Entity {
  id    Int          @id @default(autoincrement())
  attrs EntityAttr[] 
}

model EntityAttr {
  id       Int         @id @default(autoincrement())
  value    Json        // or String, doesnt matter much here
                       // the point is I need to attach info on the
                       // join table of this relation
  attr     Attr        @relation(fields: [attrId], references: [id])
  entity   Entity      @relation(fields: [entityId], references: [id])

  entityId Int
  attrId   Int

  @@unique([entityId, attrId])
}

model Attr {
  id       Int          @id @default(autoincrement())
  entities EntityAttr[]   
}
Run Code Online (Sandbox Code Playgroud)
// Solution 2
model Entity {
  id          Int          @id @default(autoincrement())
  dateAttrs   DateAttr[]
  recordAttrs RecordAttr[]
  // ... this pattern could continue for more Attr-like models
}

model DateAttr {
  id     Int       @id @default(autoincrement())
  name   String
  entity Entity    @relation(fields: [entityId], references: [id])
  value  DateTime  // Stronger typing in generated code
}

model RecordAttr {
  // ... define another Entity @relation(...)
  name   String
  value  String
  // ...
}

// ... and so on
Run Code Online (Sandbox Code Playgroud)

Please note that the schema might not be 100% complete or accurate. It is mainly to get the point across.

解决方案1的优点是数据库中的冗余和表的数量显着减少(取决于Attrs的数量)。它的失败在于令人困惑的查询、可能的特定于案例的类型转换以及每个类似模型的字段*没有代码完成。valueAttr

*prisma令人困惑的是,我的意思是,当使用自定义联接表时,简化 mn 查询的选项在功能上被禁用(例如EntityAttr

解决方案 2 有其优点,其中生成的代码会为该字段生成更强类型的代码value,但是它会减少生成的表的数量(我实际上不知道更多的表是好事还是坏事,我只知道我认为如果你有相似的值,它们应该在同一个表中)。

如果你处于我的立场,你会做什么?

小智 9

我一直在寻找合适的答案,并在这里找到了它。我不确定它是否可以应用于您的问题,但这是关于prisma和 的问题polymorphism,所以我认为这个代码片段可能对开发人员有用:

model Photo {
  id Int @id @default(autoincrement())

  likes Like[] @relation("PhotoLike")
}

model Video {
  id Int @id @default(autoincrement())

  likes Like[] @relation("VideoLike")
}

enum LikableType {
  Photo
  Video
}

model Like {
  id Int @id @default(autoincrement())

  Photo Photo? @relation("PhotoLike", fields: [likableId], references: [id], map: "photo_likableId")
  Video Video? @relation("VideoLike", fields: [likableId], references: [id], map: "video_likableId")

  likableId   Int
  likableType LikableType
}
Run Code Online (Sandbox Code Playgroud)

dbdocs 中的结果关系: 在此输入图像描述