在学习过程中向所有人提供帮助,并将Apollo和graphQL集成到我的一个项目中。到目前为止,一切正常,但是现在我试图进行一些更改,并且在输入类型和查询类型方面苦苦挣扎。我觉得这比应该的要复杂得多,因此我正在寻找有关如何处理自己情况的建议。我在网上找到的示例始终都具有非常基本的Schema,但实际情况总是更加复杂,因为我的Schema很大并且看起来如下(我将仅复制其中一部分):
type Calculation {
_id: String!
userId: String!
data: CalculationData
lastUpdated: Int
name: String
}
type CalculationData {
Loads: [Load]
validated: Boolean
x: Float
y: Float
z: Float
Inputs: [Input]
metric: Boolean
}
然后定义输入和负载,依此类推...
为此,我想要一个变体来保存“计算”,所以在同一文件中我有这个:
type Mutation {
saveCalculation(data: CalculationData!, name: String!): Calculation
}
我的解析器如下:
export default resolvers = {
Mutation: {
saveCalculation(obj, args, context) {
if(context.user && context.user._id){
const calculationId = Calculations.insert({
userId: context.user._id,
data: args.data,
name: args.name
})
return Calculations.findOne({ _id: calculationId})
}
throw new Error('Need an account to save a calculation')
}
}
}
然后我的突变如下: 从“ graphql-tag”导入gql;
export const SAVE_CALCULATION = gql`
mutation saveCalculation($data: CalculationData!, $name: String!){
saveCalculation(data: $data, name: $name){
_id
}
}
`
最后,我使用Mutation组件尝试保存数据:
<Mutation mutation={SAVE_CALCULATION}>
{(saveCalculation, { data }) => (
<div onClick={() => saveCalculation({ variables : { data: this.state, name:'name calcul' }})}>SAVE</div>
}}
</Mutation>
现在出现以下错误:
[GraphQL错误]:消息:Mutation.saveCalculation(data :)的类型 必须为输入类型,但必须为:CalculationData!。,位置:未定义, 路径:未定义
从我的研究和一些其他SO帖子中,我了解到除了查询类型外,我还应该定义输入类型,但是输入类型只能使用标量类型,但是我的模式取决于其他模式(不是标量)。当最后一个输入仅具有标量类型时,是否可以根据其他输入类型来创建输入类型?我有点迷失了,因为它似乎有很多多余之处。非常感谢您提供有关最佳做法的指导。我坚信 Apollo / graphql 可以为我的项目带来长期的帮助,但是我必须承认,当模式有些复杂时,它比我想实现的要复杂得多。在线示例通常使用String和Boolean。
答案 0 :(得分:6)
来自spec:
字段可以接受参数来配置其行为。这些输入通常是标量或枚举,但有时需要表示更复杂的值。
一个GraphQL输入对象定义了一组输入字段。输入字段可以是标量,枚举或其他输入对象。这样,参数就可以接受任意复杂的结构。
换句话说,您不能将常规GraphQLObjectType
用作GraphQLInputObjectType
字段的类型,而必须使用其他GraphQLInputObjectType
。
使用SDL写出架构时,似乎必须创建Load
类型和LoadInput
输入,尤其是在它们具有相同字段的情况下,这似乎是多余的。但是,在幕后,您定义的类型和输入将变成非常不同的对象类,每种对象具有不同的属性和方法。 GraphQLObjectType
中不存在特定于GraphQLInputObjectType
的功能(例如接受参数),反之亦然。
试图代替另一个来使用,就像试图将一个方形的钉子放在一个圆孔中。 “我不知道为什么需要一个圆。我有一个正方形。它们都有直径。为什么我都需要一个直径?”
除此之外,有充分的实际理由将类型和输入分开。这是因为在很多情况下,您将公开很多类型的字段,而这些字段不会在输入中公开。
例如,您的类型可能包括派生字段,这些派生字段实际上是基础数据的组合。或者它可能包括与其他数据之间的关系的字段(例如friends
上的User
字段)。在这两种情况下,都没有必要使这些字段成为作为某个字段的参数提交的数据的一部分。同样,您可能不想在其类型对应项上显示某些输入字段(想到的是password
字段)。
答案 1 :(得分:1)
是的,您可以:
输入对象类型上的字段本身可以引用输入对象类型,但是您不能在架构中混合输入和输出类型。输入对象类型的字段也不能有参数。
除普通类型外,还应定义输入类型。通常它们会有一些差异,例如输入将没有id或createdAt字段。