GraphQL:如何重用相同类型的查询和变异? [英] GraphQL: How to reuse same type for query and mutation?

查看:50
本文介绍了GraphQL:如何重用相同类型的查询和变异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个这样定义的查询:

Let's say I have a query defined liked this:

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

type User {
  id: ID!
  login: String!
  name: String    
}

但是现在我需要进行突变才能添加用户.我的直觉是像这样:

But now I need to have a mutation to add a user. My intuition would be to to something like this:

type Mutation {  
  addUser(newUser: User): [User]
}

但是它不起作用,因为突变不能使用查询类型".它需要使用输入类型".我知道在此示例中,这并不是很复杂,但是如果user是一个非常复杂的类型,并且使用了许多子类型.我怎样才能做到这一点?是否有将类型重新用作突变参数的方法?

But it is not working because a mutation cannot use "query type". It need to use "input type". I know that in this example, it is not really complicated to do, but if user was a really complex type with many sub-type used. How can I do that? Is there a was to re-use a type as a mutation argument?

推荐答案

不幸的是,不能使用 type 代替 input input不能代替 type .这是设计使然.从官方规范:

Unfortunately, a type cannot be used in place of an input, and an input cannot be used in place of a type. This is by design. From the official specification:

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

Fields can define arguments that the client passes up with the query, to configure their behavior. These inputs can be Strings or Enums, but they sometimes need to be more complex than this.

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

The Object type defined above is inappropriate for re‐use here, because Objects can contain fields that express circular references or references to interfaces and unions, neither of which is appropriate for use as an input argument. For this reason, input objects have a separate type in the system.

此外, GraphQLObjectType 上的字段可以具有args和resolve函数,而 GraphQLInputObjectType 上的字段则没有(但是它们具有默认值,但没有前者可用).

What's more, fields on a GraphQLObjectType can have args and a resolve function, while those on an GraphQLInputObjectType do not (but they do have default values, which are not available to the former).

从实现的角度将它们分开也是有意义的.简单的模式可能只是将字段映射到某些表中的列.但是,在实际的应用程序中,很有可能您将获得不映射到任何一列的派生字段(并且不适合在输入中使用).

It also makes sense to keep them separate from an implementation standpoint. Simple schemas are likely to just map fields to columns in some table. However, in real-world applications, it's much more likely that you'll have derived fields that don't map to any one column (and would not be appropriate to use inside an input).

您也可能只希望将一些字段用作输入(例如,如果要添加用户,则客户端不应向您发送ID;这应该在添加用户时由数据库生成).同样,您可能不想公开用作客户端输入的每个字段,而只公开它们实际需要的那些字段.

It's also likely you'll only want some fields to be used as input (if you're adding a user, for example, a client shouldn't send you an id; this should probably be generated by the db when the user is added). Likewise, you may not want to expose every field that's used as input to the client, only those they actually need.

如果没有其他问题,则输入和返回类型之间对 non-null 的使用可能会有所不同.

If nothing else, your use of non-null will probably be different between an input and a returned type.

也就是说,有一种解决方法.至少在graphql-js中.如果以编程方式声明架构,则可以使用一组字段分别定义一个对象,然后为 User UserInput 设置 fields 属性代码>对象.另外,如果您以声明方式定义架构(例如在示例中),则可以使用如下模板文字:

That said, there is something of a workaround. In graphql-js, at least. If you declare your schema programatically, you could separately define an Object with your set of fields, and then set your fields property for both your User and UserInput objects. Alternatively, if you're defining your schema declaratively (like in your example), you could use template literals like this:

const userFields = `
  id: ID!
  login: String!
  name: String
`
const schema = `
  type User {
    ${userFields}
  }
  type UserInput {
    ${userFields}
  }
`

如果需要,甚至可以遍历每个定义的类型并以编程方式创建匹配的输入类型.但是,IMO,当您考虑灵活性的成本时,为实现这些变通办法而付出的努力可能不值得.咬紧牙关,对您实际需要的内容进行一些思考,以作为该突变的输入,并仅指定您需要的字段.

Heck, if you wanted to, you could even iterate over every defined type and programatically create a matching input type. However, IMO, the effort in implementing any of these workarounds is probably not worth it when you consider the cost in flexibility. Bite the bullet, put some thought into what you actually need as an input to that mutation and specify only the fields you need.

这篇关于GraphQL:如何重用相同类型的查询和变异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆