将上下文信息绑定到GraphQL类型?

时间:2019-02-20 03:30:38

标签: javascript graphql graphql-js

假设我有两种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!

我假设我需要包装类型,例如:

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

我想知道是否存在标准化的方法?另外,我有许多现有查询直接将Classroom绑定到Student,因此引入ClassroomStudent将是API的重大改变。我有没有办法构造我的API,以允许有机地引入这些类型的更改而又不引入向后不兼容的更改?

谢谢您的时间。

1 个答案:

答案 0 :(得分:2)

与中继兼容的模式中的常见模式是将类似字段附加到相关边缘:

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
}

您可以使用必需的课堂参数为学生添加字段。如果向学生查询特定的教室,这将迫使客户端潜在地两次提供相同的教室ID,但这是有效的选择。它还具有使您无需获取教室数据就可以直接查询学生的其他好处:

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