GraphQL:如何重用同一类型进行查询和变异?

GraphQL:如何重用同一类型进行查询和变异?,graphql,Graphql,假设我定义了一个查询,如下所示: type Query { # The basic me query getUser(id:Int): [User] } type User { id: ID! login: String! name: String } 但是现在我需要一个变异来添加一个用户。我的直觉是这样的: type Mutation { addUser(newUser: User): [User] } const userFields = ` i

假设我定义了一个查询,如下所示:

type Query {
  # The basic me query
  getUser(id:Int): [User]
}

type User {
  id: ID!
  login: String!
  name: String    
}
但是现在我需要一个变异来添加一个用户。我的直觉是这样的:

type Mutation {  
  addUser(newUser: User): [User]
}
const userFields = `
  id: ID!
  login: String!
  name: String
`
const schema = `
  type User {
    ${userFields}
  }
  type UserInput {
    ${userFields}
  }
`
但它不起作用,因为变异不能使用“查询类型”。它需要使用“输入类型”。我知道在这个例子中,这并不是很复杂,但如果用户是一个非常复杂的类型,使用了很多子类型。我该怎么做?
是否存在重复使用类型作为突变参数的方法?

不幸的是,
类型
不能代替
输入
,而
输入
不能代替
类型
。这是故意的。从:

字段可以定义客户端随查询传递的参数, 配置他们的行为。这些输入可以是字符串或枚举,但 它们有时需要比这更复杂

上面定义的对象类型不适合在此处重复使用, 因为对象可以包含表示循环引用或 对接口和联合的引用,两者都不合适 用作输入参数。因此,输入对象具有 系统中的独立类型

此外,
GraphQLInputObjectType
上的字段可以有参数和解析函数,而
GraphQLInputObjectType
上的字段则没有(但它们有默认值,而前者不可用)

从实现的角度来看,将它们分开也是有意义的。简单模式可能只是将字段映射到某些表中的列。然而,在现实世界的应用程序中,更可能的情况是派生字段不映射到任何一列(并且不适合在输入中使用)

您也可能只希望一些字段用作输入(例如,如果您正在添加用户,客户端不应向您发送id;添加用户时,db可能会生成id)。同样,您可能不想公开每个用作客户机输入的字段,只公开它们实际需要的字段

如果没有其他内容,则在输入类型和返回类型之间使用的
非null
可能会有所不同

也就是说,至少在graphql js中有一些变通方法。。如果以编程方式声明模式,则可以使用字段集分别定义对象,然后为
User
UserInput
对象设置
fields
属性。或者,如果以声明方式定义模式(如示例中所示),则可以使用如下模板文本:

type Mutation {  
  addUser(newUser: User): [User]
}
const userFields = `
  id: ID!
  login: String!
  name: String
`
const schema = `
  type User {
    ${userFields}
  }
  type UserInput {
    ${userFields}
  }
`
见鬼,如果你想,你甚至可以迭代每一个定义的类型,并通过编程创建一个匹配的输入类型。然而,IMO,当你考虑到灵活性的成本时,实施这些方法的努力可能不值得。咬紧牙关,把你真正需要的东西作为变异的输入,只指定你需要的字段