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

查看:18
本文介绍了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]
}

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

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 不能代替 inputinput 不能代替 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 和解析函数,而 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 中.如果您以编程方式声明您的架构,您可以分别定义一个带有您的字段集的对象,然后为您的 UserUserInputfields 属性代码>对象.或者,如果您以声明方式定义架构(例如在您的示例中),您可以使用这样的模板文字:

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天全站免登陆