Skip to content

Instantly share code, notes, and snippets.

@nikolasburk
Created January 15, 2021 16:00
Show Gist options
  • Save nikolasburk/17650171aa21c7826e35938a34e45da9 to your computer and use it in GitHub Desktop.
Save nikolasburk/17650171aa21c7826e35938a34e45da9 to your computer and use it in GitHub Desktop.

In Prisma 1, it wasn't necessary to specify both sides of a relation, this means this was allowed:

type User {
  id: ID! @unique @id
  questions: [Question]
}

type Question {
  id: ID! @unique @id
}

This only specifies one side of the relation, from User to Question, but not the other way around. If you wanted to be explicit about the second relation side, the datamodel would look as follows:

type User {
  id: ID! @unique @id
  questions: [Question]
}

type Question {
  id: ID! @unique @id
  user: User # now you have a second side of the relation
}

In fact, Prisma 1 automatically infers this field. So even if you don't specify it as in the first code snippet above, it does exist implicitly (as a foreign key in the underlying database schema and as a field in your generated GraphQL schema).

In Prisma 2, the first version would not be allowed, you always must specify both sides of the relation. The corresponding Prisma 2 schema looks as follows:

model User {
  id        String     @id @default(cuid())
  questions Question[]
}

model Question {
  id     String @id @default(cuid())
  user   User   @relation(fields: [userId], references: [id]) // this is required in Prisma 2
  userId String @map("user")                                  // this is required in Prisma 2
}

Note that we're using @map("user") to map the userId field in the Prisma schema to the user column in the database. This is only necessary because the column was created by Prisma 1 and is called user. If you start out with Prisma 2 in a fresh project, the schema would typically look as follows (basically the same but without the extra @map):

model User {
  id        String     @id @default(cuid())
  questions Question[]
}

model Question {
  id     String @id @default(cuid())
  user   User   @relation(fields: [userId], references: [id]) // this is required in Prisma 2
  userId String                                               // this is required in Prisma 2
}

Now, one issue with your Prisma 1 datamodel was that you specified both sides of a relation, but you added different names for the relation via the Prisma 1 @relation directive, for example:

type User {
  id: ID! @unique @id
  questions: [Question] @relation(name: "QuestionsUser")
}

type Question {
  id: ID! @unique @id
  poster: User! @relation(name: "QuestionPoster")
}

Here, you explicitly told Prisma 1 that these relation fields do not "belong together". Consequently, Prisma implicitly added the second side of the relation implicitly to the schema (similar to the example above)! This means, the actual schema that Prisma 1 created for you under the hood looked as follows:

type User {
  id: ID! @unique @id
  questions: [Question] @relation(name: "QuestionsUser")
  questions_QuestionPoster("QuestionPoster") # I'm actually not sure if this is the correct field name, but it should be somewhat similar
}

type Question {
  id: ID! @unique @id
  user: User @relation(name: "QuestionsUser")
  poster: User! @relation(name: "QuestionPoster")
}

As I mention in the comment, I'm actually not sure if questions_QuestionPoster is the correct field name Prisma 1 generates here, but it should be somewhat similar. Prisma 1 can't call it questions (which would be the default) because the existing field is already called like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment