假设我有一个查询定义喜欢这个:
type Query {
# The basic me query
getUser(id:Int): [User]
}
type User {
id: ID!
login: String!
name: String
}
但是现在我需要一个变异来添加用户。我的直觉是这样的事情:
type Mutation {
addUser(newUser: User): [User]
}
但它不起作用,因为突变不能使用“查询类型”。它需要使用“输入类型”。我知道在这个例子中,它并不是很复杂,但如果用户是一个非常复杂的类型,使用了很多子类型。我怎样才能做到这一点? 有没有将类型重新用作变异参数?
答案 0 :(得分:4)
不幸的是,type
不能用来代替input
,而input
不能用来代替type
。这是设计的。来自official specification:
字段可以定义客户端使用查询传递的参数, 配置他们的行为。这些输入可以是字符串或枚举,但是 他们有时需要比这更复杂。
上面定义的对象类型不适合在这里重复使用, 因为对象可以包含表示循环引用的字段或 对接口和联合的引用,两者都不合适 用作输入参数。出于这个原因,输入对象有一个 系统中的单独类型。
除此之外,GraphQLObjectType
上的字段可以有args和resolve函数,而GraphQLInputObjectType
上的字段则没有(但是它们有默认值,但是它们不可用前者。
将它们与实现角度分开也是有意义的。简单模式可能只是将字段映射到某些表中的列。但是,在实际应用程序中,您更有可能导出不会映射到任何一列的字段(并且不适合在输入中使用)。< / p>
您也可能只想将某些字段用作输入(如果您要添加用户,例如,客户端不应该&#39 ; t发送给你一个id;这应该是在添加用户时由db生成的)。同样,您可能不希望将用作输入的每个字段暴露给客户端,只显示他们实际需要的字段。
如果不出意外,您对non-null
的使用在输入和返回类型之间可能会有所不同。
也就是说,有一些解决方法。至少在graphql-js中。如果以编程方式声明架构,则可以使用一组字段单独定义对象,然后为fields
和User
对象设置UserInput
属性。或者,如果您以声明方式(例如在您的示例中)定义模式,则可以使用如下模板文字:
const userFields = `
id: ID!
login: String!
name: String
`
const schema = `
type User {
${userFields}
}
type UserInput {
${userFields}
}
`
哎呀,如果你愿意,你甚至可以迭代每个定义的类型,并以编程方式创建匹配的输入类型。但是,IMO,当您考虑灵活性的成本时,实施任何这些变通方法的努力可能是不值得的。咬紧牙关,考虑一下你实际需要什么作为该变异的输入,并只指定你需要的字段。