Связывание контекстной информации в тип GraphQL? - PullRequest
0 голосов
/ 20 февраля 2019

Допустим, у меня есть два типа GraphQL:

type Student {
  id: ID!
  name: String!
}

type Classroom {
  id: ID!
  students: [Student!]!
}

type Query {
  classroom(id: ID!): Classroom!
}

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

{
  classroom(id: 1) {
    id
    students {
      id
      name
    }
  }
}

И с правильными установленными преобразователями, этовернул бы мне учеников, связанных с определенным классом.

Однако, скажем, я хотел найти некоторую информацию, касающуюся успеваемости студента в классе, скажем:

averageTestScore: Int!
numAbsences: Int!

IПредположим, мне понадобится тип оболочки, например:

type ClassroomStudent {
  averageTestScore: Int!
  numAbsences: Int!
  student: Student!
}

Мне было интересно, существует ли стандартизированный способ сделать это?Кроме того, у меня есть много существующих запросов, которые напрямую связывают Classroom с Student, поэтому введение ClassroomStudent было бы серьезным изменением API.Могу ли я спроектировать свои API-интерфейсы так, чтобы эти виды изменений были вполне органично представлены без внесения изменений, несовместимых с предыдущими версиями?

Спасибо за ваше время.

1 Ответ

0 голосов
/ 20 февраля 2019

Обычным шаблоном в схемах, совместимых с Relay, является прикрепление таких полей к соответствующему ребру:

type StudentConnection {
  pageInfo: PageInfo
  edges: [StudentEdge!]!
}

type StudentEdge {
  cursor: String!
  node: Student!
  averageTestScore: Int!
  numAbsences: Int!
}

type Classroom {
  students: StudentConnection!
  # other fields
}

Однако это все равно, фактически, введение введенного вами ClassroomStudent.В любом случае, хитрость для введения такого изменения без нарушения вашего API состоит в том, чтобы сохранить (и осудить) предыдущее поле и ввести новое под другим именем:

type Classroom {
  students: [Student!]! @deprecated(reason: "Use classroomStudents instead")
  classroomStudents: [ClassroomStudent!]!
  # other fields
}

Это может выглядеть не очень красиво,но это позволит вашим клиентским приложениям переходить, не имея дело с критическими изменениями.

Еще один потенциальный вариант:

type Student {
  performance(classroom: ID!): StudentPerformance
}

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

query {
  students {
    id
    performance(classroom: 1) {
      averageTestScore
      numAbsences
    }
  }
}
...