postgresql 在我的Prisma模式中定义/设计这些相关的Postgres表

eni9jsuy  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(145)

我的应用程序使用Prisma,用户可以创建许多项目。这些项目类似于文本文档,但具有一些辅助组织的附加属性。
这些项目将始终由最初创建它们的用户“拥有”,并且该用户可以控制其他用户的管理访问权限,无论是查看、评论还是编辑。在应用程序中,可以访问其他用户的项目的用户被视为“协作者”。
在当前的应用程序体系结构中,用户可以创建和拥有许多协作者,并且创建用户可以完全控制协作者可以访问他们的哪些项目以及访问的程度-查看,评论,编辑。
应用程序中的用户携带与用户相关的常规元数据,如姓名和电子邮件。应用程序中的项目携带与项目相关的数据,如项目名称和其他属性。
我创建了一个存储用户协作者(users)的表,以便在用户可以为协作者执行CRUD操作的页面上显示这些协作者的列表。
为了在主页上向用户显示与他们相关联的项目,我创建了另一个表,该表引用项目及其相关用户,并添加了一个角色,该角色定义该用户是所有者还是协作者。
这允许我在应用程序的主页上显示用户可以访问的项目,无论用户是创建项目还是仅仅是一个协作者。
因此,当用户登录并转到其主页时,他们看到的是一个完整的项目列表,其中他们要么是所有者,要么只是合作者。
对于列表中用户是所有者的项目,我需要显示一个代表该项目协作者的化身列表。
我为什么要做

  • 是否创建另一个表来定义从项目到协作者的关系/关联?
  • 以更大的方式重新考虑我的模式/数据库设计?
model User {
  id                   String                   @id @default(cuid())
  name                 String?
  email                String?                  @unique
  emailVerified        DateTime?
  image                String?
  accounts             Account[]
  sessions             Session[]
  collaborator         UserCollaborator[]       @relation("Collaborator")
  userCollaborators    UserCollaborator[]       @relation("UserCollaborators")
  collabInviteReceived UserCollaboratorInvite[] @relation("InviteReceived")
  collabInviteSent     UserCollaboratorInvite[] @relation("InviteSent")
  userProjects         UserProject[]
}

model Project {
  id           String        @id @default(cuid())
  name         String?
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt
  things       Thing[]
  userProjects UserProject[]
}

model UserProject {
  projectId                String
  roleId                   Int
  userId                   String
  createdAt                DateTime                  @default(now())
  updatedAt                DateTime                  @updatedAt
  project                  Project                   @relation(fields: [projectId], references: [id], onDelete: Cascade)
  role                     Role                      @relation(fields: [roleId], references: [id])
  user                     User                      @relation(fields: [userId], references: [id])
  userCollaboratorProjects UserCollaboratorProject[]

  @@id([userId, projectId])
}

model UserCollaborator {
  ownerId                  String
  collaboratorId           String
  roleId                   Int
  status                   CollaboratorStatusEnum
  // this is the user who is the collaborator
  collaborator             User                      @relation("Collaborator", fields: [collaboratorId], references: [id])
  // this is the user who created the collaborator
  owner                    User                      @relation("UserCollaborators", fields: [ownerId], references: [id])
  role                     Role                      @relation(fields: [roleId], references: [id])
  userCollaboratorProjects UserCollaboratorProject[]

  @@id([ownerId, collaboratorId])
}

model UserCollaboratorProject {
  userProjectProjectId           String
  userProjectUserId              String
  userCollaboratorOwnerId        String
  userCollaboratorCollaboratorId String
  userCollaborator               UserCollaborator @relation(fields: [userCollaboratorOwnerId, userCollaboratorCollaboratorId], references: [ownerId, collaboratorId], onDelete: Cascade)
  userProject                    UserProject      @relation(fields: [userProjectUserId, userProjectProjectId], references: [userId, projectId], onDelete: Cascade)

  @@id([userProjectUserId, userProjectProjectId, userCollaboratorOwnerId, userCollaboratorCollaboratorId])
}

字符串

798qvoo8

798qvoo81#

设计中的一个问题是将项目所有者与项目协作者区分开来。它们是重叠的。例如,当您要列出某个用户参与的所有项目时。
你可以通过定义一个新的实体来解决这个问题,我称之为“项目参与者”。这是参与项目的每个人:所有者、管理员、查看者、编辑等。这就是你想要列出的。
另一个问题是让合作者由拥有项目的用户“拥有”。这是数据复制。它带来了合作者的所有者可能不是项目的所有者的可能性。
合作者应该是项目的“所有者”,他们可以从项目中找到项目的所有者,这样就消除了数据重复,合作者的所有者不可能与项目的所有者不同,而且还可以改变谁“拥有”合作者的定义。
业务规则会改变,即使您被承诺不会改变。架构应该努力只对基本关系进行硬编码。业务规则应该在数据或软件中完成。即使规则没有改变,这也会使您的设计在附加功能方面更加灵活。
我将提出这些实体...

User
  id
  name
  email
  ...
  has many ProjectParticipants
  has many Projects through ProjectParticipants

Project
  name
  ...
  has many ProjectParticipants
  has many Users through ProjectParticipants

ProjectRoles
  id
  name

ProjectParticipant
  belongs to a User
  belongs to a Project
  has many ProjectRoles

字符串
项目涉及的每个用户都是项目参与者。
每个ProjectParticipant都有一个或多个ProjectRoles。这些角色可以是查看、编辑、注解和所有者。
您可以通过加入ProjectParticipants来列出用户的所有项目。
当用户创建一个项目时,您可以让他们成为拥有所有者角色的ProjectParticipant。
您可以将“协作者”定义为不具有所有者角色的ProjectParticipant。
角色的作用不是在架构中定义的,而是在软件中定义的。在您的情况下,您只允许该项目中ProjectRole为“owner”的ProjectParticipants对其他ProjectParticipants进行更改。您可以稍后更改此设置,以允许(例如)“admin”对ProjectParticipants进行更改。
ProjectRoles只是一个所有可能角色的列表。它将以一个id和一个单词开始。它可以是一个enum,但最好是一个联接表。这样可以让你重命名角色,而不必更改每个人的数据。它使一些查询更容易有一个联接表,如枚举每个角色。它允许角色在以后通过添加行变得更复杂。
Demonstration的一个。

相关问题