【发布时间】:2022-02-05 04:57:25
【问题描述】:
我遇到了一个无法自行解决的问题。让我们一步一步来指出问题所在。
- 我有一个突变
bookAppointment,它返回一个Appointment对象 - GraphQL 架构表示该对象应返回 4 个属性:
id、date、specialist、client。 - 要遵循 GraphQL 样式,
specialist和client属性应该是字段级解析器 - 要获取此对象,我需要将
specialistId传递给专家字段级解析器,并将clientId传递给客户端字段级解析器。 - 此时出现问题。
-
client、specialist的字段级解析器期望根突变返回像clientId和specialistId这样的字段。但是 GraphQL 语法和由该语法生成的类型不包括这个道具(有意义)。 - 如何“扩展”解析器的返回类型及其
interface BookAppointmentPayload以使我和 TypeScript 满意?
这是我的 GraphQL 架构
type Client {
id: ID!
name: String!
}
type Specialist {
id: ID!
name: String!
}
type Appointment {
id: ID!
date: Date!
client: Client!
specialist: Specialist!
}
input BookAppointmentInput {
date: Date!
userId: ID!
specialistId: ID!
}
type BookAppointmentPayload {
appointment: Appointment!
}
type Mutation {
bookAppointment(input: BookAppointmentInput!): BookAppointmentPayload!
}
这是 GraphQL 模式的 TypeScript 表示
interface Client {
id: string
name: string
}
interface Specialist {
id: string
name: string
}
interface Appointment {
id: string
date: Date
client: Client
specialist: Specialist
}
interface BookAppointmentPayload {
appointment: Appointment
}
在这里我定义了我的解析器对象
const resolvers = {
...
Mutation: {
bookAppointment: (parent, args, context, info): BookAppointmentPayload => {
return {
appointment: {
id: '1',
date: new Date(),
clientId: '1', // This prop doesn't exist in the TypeScript interface of Appointment, but is required for the field-level resolver of a `client` prop
specialistId: '1' // This prop doesn't exist int he TypeScript interface of Appointment, but is required for the field-level resolver of a `specialist` prop
}
}
}
},
Appointment: {
client: (parent, args, context, info) => {
// I need a clientId (e.g. args.clientId) to fetch the client object from the database
return {
id: '1',
name: 'Jhon'
}
},
specialist: (parent, args, context, info) => {
// I need a specialistId (e.g. args.specialistId) to fetch the specialist object from the database
return {
id: '1',
name: 'Jane'
}
}
}
}
我想到的解决方案:
- 创建一个表示解析器“实际”返回类型的接口
...
interface Apppointment {
id: string
date: Date
clientId: string // instead of `client: Client`
specialistId: string // instead of `specialist: Specialist`
}
interface BookAppointmentPayload {
appointment: Appointment
}
...
但这并不反映 GraphQL 类型。此外,graphql-generator 之类的工具会使用应包含在响应中的实际对象生成类型,而不是字段级解析器将使用的字段。 (我错了吗?)
我想知道您是如何解决此类问题的?
【问题讨论】:
-
这是一个常见问题,我过去解决它的方法是将
clientId和specialistId预先作为类型的一部分,这样你就有了“指向”的东西对那些对象。如果您反对在类型中包含这些,则需要在数据库所持有的任何等效项中具有一些底层结构,即具有隐藏的 id 字段来访问这些引用。一般来说,您可以在您的Appointment界面上拥有这些,或者让client和specialist指向约会(这在客户可以有很多约会的情况下很有用) -
感谢您的回复。 “这是一个常见问题”我在生成器工具和 graphql doc 本身中都找不到任何提及。将此道具放入 GraphQL 架构中似乎是一种重复,其中通过
appointmentId从数据库中获取client和specialist的性能并不是最优的。
标签: graphql apollo-server