Моделирование данных GraphQL - расширенные типы (Prisma)

В моей модели данных Prisma я начал с такого базового типа пользователя:

type User {
  name: String!
  email: String! @unique
  password: String!
}

Теперь у пользователя может быть две роли: либо кандидат, либо пользователь, связанный с работодателем. Если кандидат, пользователь также должен иметь набор приложений и набор квалификаций, если он связан с работодателем, он должен иметь уровень доступа и ссылку на работодателя.

Во-первых, есть ли способ расширить базовые типы в моделировании данных GraphQL? Если да, то как мне это сделать?

Если нет, я вижу три разных используемых метода, и мне любопытно, каковы плюсы и минусы каждого подхода:

  1. Имея два отдельных типа CandidateUser и EmployerUser, каждый с полями name, email, password. Я вижу две проблемы с этим подходом: тег @unique в email ненадежен, и мне пришлось бы написать специальную проверку, чтобы убедиться, что поле уникально для обоих типов; и наличие единой функции входа в систему, которая принимает электронную почту и извлекает соответствующие данные пользователей, больше не является тривиальным: необходимо выполнять поиск в обеих таблицах.

Нравится:

    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!
    }
  1. Снова два отдельных типа, но с RootUser, содержащим name, email и password, и с CandidateUser и EmployerUser, каждый из которых имеет однозначную ссылку на RootUser. Это приведет к применению тега @unique в поле электронной почты, но поиск по-прежнему будет нетривиальным.

    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!
    }
    
  2. Расширение User, чтобы поля в EmployerUser и CandidateUser были необязательными параметрами. Это довольно простой подход, но мне понадобится настраиваемая обработка для обеспечения обязательных полей (например, я не могу отметить, например, работодателя, как требуется, поскольку это поле не будет существовать для кандидата).

    type User{
      name: String!
      email: String! @unique
      password: String!
      applications: [Application!]!
      qualifications: [Qualification!]!
      employer: Employer
      accessRight: AccessRight
    }
    

Я действительно хочу спросить, есть ли лучший способ решить эту проблему. Я все еще новичок в GraphQL и не лучший разработчик данных для начала, но я бы высоко оценил любое подталкивание в правильном направлении :)

И если у меня нет другого выбора, кроме трех, которые я перечислил, какой из них будет наиболее разумным?


person Lars Holdaas    schedule 10.09.2018    source источник


Ответы (1)


Вы пытаетесь реализовать тип интерфейса:

Интерфейс - это абстрактный тип, который включает определенный набор полей, которые тип должен включать для реализации интерфейса.

interface User {
  name: String!
  email: String! @unique
  password: String!
}

Это означает, что любой тип, реализующий User, должен иметь именно эти поля с этими аргументами и возвращаемыми типами. Итак, теперь ваш Candidate тип может реализовывать User:

type Candidate implements User {
  name: String!
  email: String! @unique
  password: String!
  applications: [Application!]!
  qualifications: [Qualification!]!
}

Интерфейсы полезны, когда вы хотите вернуть объект или набор объектов, но они могут быть нескольких разных типов. Дополнительную информацию см. В документации по абстрактному типу интерфейса. .


Обновление:

Поскольку сейчас это вопрос Prisma GraphQL, вы должны знать, что Prisma пока не поддерживает интерфейсы или типы объединения. Проблема № 83 и проблема № 165 обсуждаются соответственно как запросы функций.

Тем не менее, есть эта отличная статья, в которой обсуждаются обходные пути для такого подхода:

Интерфейсы GraphQL (и типы объединения) с Prisma и Yoga

Что сводится к 2 вариантам:

  1. Сохранение всех данных с дополнительными типами полей в Prisma под одним типом (интерфейсом) с последующим разделением данных между примитивными типами на сервере приложений.
  2. Хранение данных в каждом примитивном типе на Prisma и сшивание вещей для запросов на сервере приложений.
person U-ways    schedule 10.09.2018
comment
Итак, если и Candidate, и EmployerUser реализуют User, будет ли электронное письмо: String! @unique обеспечивать, чтобы этот адрес электронной почты был уникальным как для Candidates, так и для EmployerUser, или только в каждом поле? - person Lars Holdaas; 10.09.2018
comment
О, теперь я вижу, что Prisma не поддерживает интерфейсы, так что я все еще застрял - person Lars Holdaas; 10.09.2018
comment
@LarsHoldaas Я плохо подумал, что вы задаете простой вопрос GraphQL. (Я только что добавил тег prisma). Типы интерфейсов для проблемы с prisma-graphql обсуждались здесь: выпуск №83. В этой проблеме должны быть какие-то обходные пути. - person U-ways; 10.09.2018
comment
В любом случае это был отличный ответ! Я думал, что мой вопрос был общим вопросом GraphQL, пока я не прочитал ваш ответ, а затем обнаружил, что Prisma не поддерживает его, поэтому я сам не пометил его. Я должен иметь это в виду для будущих вопросов. - person Lars Holdaas; 10.09.2018