假设我有一个像这样定义的查询:
type Query {
# The basic me query
getUser(id:Int): [User]
}
type User {
id: ID!
login: String!
name: String
}
Run Code Online (Sandbox Code Playgroud)
但现在我需要有一个突变来添加一个用户。我的直觉是这样的:
type Mutation {
addUser(newUser: User): [User]
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用,因为突变不能使用“查询类型”。它需要使用“输入类型”。我知道在这个例子中,做起来并不复杂,但是如果用户是一个非常复杂的类型,使用了许多子类型。我怎样才能做到这一点?是否需要重新使用类型作为突变参数?
不幸的是, atype不能代替 an input,并且 aninput不能代替 a type。这是设计使然。从官方规范:
字段可以定义客户端通过查询传递的参数,以配置它们的行为。这些输入可以是字符串或枚举,但它们有时需要比这更复杂。
上面定义的对象类型不适合在这里重用,因为对象可以包含表达循环引用或对接口和联合的引用的字段,这两者都不适合用作输入参数。因此,输入对象在系统中具有单独的类型。
更重要的是,a 上的字段GraphQLObjectType可以有 args 和解析函数,而 a上的字段GraphQLInputObjectType没有(但它们确实有默认值,前者不可用)。
从实现的角度来看,将它们分开也是有意义的。简单模式可能只是将字段映射到某些表中的列。但是,在实际应用程序中,您更有可能拥有不映射到任何一列的派生字段(并且不适合在输入中使用)。
您也可能只希望将某些字段用作输入(例如,如果您要添加用户,则客户端不应向您发送 id;这可能应该在添加用户时由数据库生成)。同样,您可能不想向客户端公开用作输入的每个字段,只公开他们实际需要的字段。
如果不出意外,您non-null对输入和返回类型的使用可能会有所不同。
也就是说,有一些解决方法。至少在 graphql-js 中。如果您以编程方式声明架构,则可以使用您的字段集单独定义一个对象,然后fields为您的User和UserInput对象设置您的属性。或者,如果您以声明方式定义架构(例如在您的示例中),您可以使用这样的模板文字:
const userFields = `
id: ID!
login: String!
name: String
`
const schema = `
type User {
${userFields}
}
type UserInput {
${userFields}
}
`
Run Code Online (Sandbox Code Playgroud)
哎呀,如果您愿意,您甚至可以遍历每个定义的类型并以编程方式创建匹配的输入类型。但是,IMO,当您考虑灵活性成本时,实施任何这些变通方法的努力可能不值得。咬紧牙关,考虑一下您实际需要什么作为该突变的输入,并仅指定您需要的字段。
| 归档时间: |
|
| 查看次数: |
3072 次 |
| 最近记录: |