Search code examples
javascriptnode.jstypescriptdatabaseprisma

Many to one in prisma


Is it possible to relate two or more fields to a single matrix in the prism?

I'm trying this:

model Match {
  id            String @id @default(uuid())
  tournament_id String
  team_one_id   String
  team_two_id   String

  tournament Tournament? @relation(fields: [tournament_id], references: [id])
  team_one   Team        @relation(fields: [team_one_id], references: [id])
  team_two   Team        @relation(fields: [team_two_id], references: [id])

  @@map("matches")
}

model Team {
  id       String @id @default(uuid())
  owner_id String
  matches Match[]

  @@map("teams")
}

But I am getting the following error:error


Solution

  • If two fields on a model are relational fields that refer to the same model (Team in this case), you need to prove the name argument to @relation.

    Documentation: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#relation

    In your schema, you would need to specify the name of the relationship like this:

    model Match {
      id            String @id @default(uuid())
      tournament_id String
      team_one_id   String
      team_two_id   String
    
      tournament Tournament? @relation(fields: [tournament_id], references: [id])
      team_one   Team        @relation(fields: [team_one_id], references: [id], name: "matches_team_one")
      team_two   Team        @relation(fields: [team_two_id], references: [id], name: "matches_team_two")
    
      @@map("matches")
    }
    
    model Team {
      id       String @id @default(uuid())
      owner_id String
      matchesTeamOne Match[] @relation(name: "matches_team_one")
      matchesTeamTwo Match[] @relation(name: "matches_team_two")
    
      @@map("teams")
    }
    

    This doesn't really work at scale because you NEED to define two separate relation fields on the Match and Team model. Why not define the teams field as an array on Match so you only need to do it once?

    model Match {
      id            String @id @default(uuid())
      tournament_id String
      team_one_id   String
      team_two_id   String
    
      tournament Tournament? @relation(fields: [tournament_id], references: [id])
      teams Team[]
    
      @@map("matches")
    }
    
    model Team {
      id       String @id @default(uuid())
      owner_id String
      matches  Match[]
    
      @@map("teams")
    }
    

    The caveat with this solution is that you have to validate at your backend level that the teams field only ever has 2 connected teams, no more and no less. But it makes the relationship more transparent to developers and easier to manage under the hood.