Reputation: 750
In my Prisma Data Model I started out with a basic User type like this:
type User {
name: String!
email: String! @unique
password: String!
}
Now a User can have two roles: either as a candidate or as a user associated with an employer. If a candidate, the user should also have a set of applications and a set of qualifications, if associated with an employer it should have an access level and a reference to the employer.
First off, is there any way to extend basic types in GraphQL data modelling? If so, how would I go about doing it?
If there is not, I can see three different methods used, and I'm curious what are the pros and cons of each approach:
CandidateUser
and EmployerUser
, each with the fields name
, email
, password
. I see two problems with this approach: The @unique
tag on email
is not reliable, and I would have to write a custom verification to make sure the field is unique across both types; and having a single login-function that takes email and fetches the users corresponding data is no longer trivial: it needs to do a lookup in both tables. Like this:
type CandidateUser {
name: String!
email: String! @unique
password: String!
applications: [Application!]!
qualifications: [Qualification!]!
}
type EmployerUser{
name: String!
email: String! @unique
password: String!
employer: Employer!
accessRight: AccessRight!
}
Again two separate types, but with a RootUser
containing name
, email
and password
, and with CandidateUser
and EmployerUser
each having a one-to-one reference to a RootUser
. This would enforce the @unique
tag on the email field, but lookup would still be nontrivial.
type RootUser{
name: String!
email: String! @unique
password: String!
}
type CandidateUser {
rootUser: RootUser!
applications: [Application!]!
qualifications: [Qualification!]!
}
type EmployerUser{
rootUser: RootUser!
employer: Employer!
accessRight: AccessRight!
}
Extending User
to have the fields within EmployerUser and CandidateUser as optional parameters. This is a pretty simple approach, but I would need custom handling to enforce requiring fields (as in, I can not mark for instance employer as required as that field would not exist for a Candidate).
type User{
name: String!
email: String! @unique
password: String!
applications: [Application!]!
qualifications: [Qualification!]!
employer: Employer
accessRight: AccessRight
}
I really want to ask if there is a better way of solving this. I'm still pretty new to GraphQL and not the best data modeler to begin with, but I'd greatly appraciate any nudge in the right direction :)
And if I do not have any other choice but the three I listed, which one would make the most sense?
Upvotes: 0
Views: 1821
Reputation: 7714
What you're trying to do is implementing an interface type:
An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface.
interface User {
name: String!
email: String! @unique
password: String!
}
This means that any type that implements User
needs to have these exact fields, with these arguments and return types. So now your Candidate
type can implement User
:
type Candidate implements User {
name: String!
email: String! @unique
password: String!
applications: [Application!]!
qualifications: [Qualification!]!
}
Interfaces are useful when you want to return an object or set of objects, but those might be of several different types. Have a look at the interface abstract type documentation for more information.
Update:
Since this is a Prisma GraphQL question now, you should be aware that Prisma does not support Interfaces or Union Types as yet. Issue #83 and issue #165 discuss both respectively as feature requests.
However, there is this great article that discuss the workarounds for such approach:
GraphQL Interfaces (and Union Types) with Prisma and Yoga
Which boils down to 2 options:
- Storing all data with optional type-specific fields under one type (the interface) in Prisma, and then splitting the data back between the primitive types in the app server.
- Storing the data in each primitive type on Prisma, and stitching things for queries on the app server.
Upvotes: 2