多对多自关系 Prisma - 一个字段

JSi*_*Sim 7 schema many-to-many prisma prisma-graphql

我正在尝试使用 Prisma 和其他工具为我的应用程序创建一个友谊机制。在文档中,它显示了以下示例,说明如何创建多对多自关系:

model User {
  id         Int       @id @default(autoincrement())
  name       String?
  followedBy Follows[] @relation("following")
  following  Follows[] @relation("follower")
}

model Follows {
  follower    User @relation("follower", fields: [followerId], references: [id])
  followerId  Int
  following   User @relation("following", fields: [followingId], references: [id])
  followingId Int

  @@id([followerId, followingId])
}
Run Code Online (Sandbox Code Playgroud)

我已经实现了这个并且它有效,但是问题是对于友谊来说,没有“关注”和“跟随者”,你们只是朋友。目前,当我查询时,我必须查询这两个字段才能找到用户的所有朋友。有没有办法只用一个字段来定义这种类型的关系?那么我们只有一个用户的好友列表吗?

bra*_*ahn 8

我同意,如果 Prisma 能够更原生地支持这种关系应该是对称的自我关系(例如,当且仅当 userB 是 userA 的朋友时,userA 是 userB 的朋友),那就太好了。

然而,据我所知,Prisma 坚持认为这种关系有两个“方面”。(如果有人更了解,我很想听听!)因此,接下来是我正在采取的方法,它避免了必须查询这两个关系才能找到用户的完整朋友集。

概念

  1. 我们将使用关系的一个“侧面”来包含完整的朋友集。另一“面”的存在只是为了满足 Prisma 的要求,我们永远不会直接查询它。

  2. 添加或删除好友关系时,我们将进行两次 prisma 调用,一次更新每个对象。

代码

架构文件:

model User {
  id         Int       @id @default(autoincrement())
  name       String?
  friends    User[]    @relation("UserFriends")

  // This second "side" of the UserFriends relation exists solely 
  // to satisfy prisma's requirements; we won't access it directly.
  symmetricFriends  User[] @relation("UserFriends")
}
Run Code Online (Sandbox Code Playgroud)

添加和删​​除好友的方法(这里有很多多余的代码可以抽象出来,但我认为这样读起来更清楚):

model User {
  id         Int       @id @default(autoincrement())
  name       String?
  friends    User[]    @relation("UserFriends")

  // This second "side" of the UserFriends relation exists solely 
  // to satisfy prisma's requirements; we won't access it directly.
  symmetricFriends  User[] @relation("UserFriends")
}
Run Code Online (Sandbox Code Playgroud)

通过这种方法,人们可以加载用户并以预期的方式获取他们所有的朋友,例如

const addFriendship = async (userIdA: string, userIdB: string) => {
  await prisma.user.update({
    where: {id: userIdA},
    data: {friends: {connect: [{id: userIdB}]}},
  });
  await prisma.user.update({
    where: {id: userIdB},
    data: {friends: {connect: [{id: userIdA}]}},
  });
};

const removeFriendship = async (userIdA: string, userIdB: string) => {
  await prisma.user.update({
    where: {id: userIdA},
    data: {friends: {disconnect: [{id: userIdB}]}},
  });
  await prisma.user.update({
    where: {id: userIdB},
    data: {friends: {disconnect: [{id: userIdA}]}},
  });
}
Run Code Online (Sandbox Code Playgroud)