当我在学习过程中以及将Apollo和graphQL集成到我的一个项目中时,所有人都会接触到你们 . 到目前为止它还可以,但现在我想尝试一些突变,我正在努力使用Input类型和Query类型 . 我觉得它比它应该更复杂,因此我正在寻找关于如何管理我的情况的建议 . 我在网上找到的例子总是有非常基本的模式,但现实总是比较复杂,因为我的模式非常大,看起来如下(我只复制一部分):
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! . ,Location:undefined,Path:undefined
从我的研究和其他一些SO帖子中,除了Query类型之外,我还应该定义输入类型,但输入类型只能是标量类型,但我的模式依赖于其他模式(这不是标量) . 当最后一个只有标量类型时,我可以根据其他输入类型等创建输入类型吗?我有点失落,因为它似乎有很多冗余 . 非常感谢对最佳实践的一些指导 . 我确信 Apollo/graphql 可以在我的项目中为我带来很好的帮助,但是我不得不承认,当Schemas有点复杂时,它比我想象的要复杂得多 . 在线示例通常坚持使用String和Boolean .
2 回答
来自spec:
换句话说,您不能使用常规
GraphQLObjectType
作为GraphQLInputObjectType
字段的类型 - 您必须使用另一个GraphQLInputObjectType
.当您使用SDL编写模式时,必须创建
Load
类型和LoadInput
输入似乎是多余的,特别是如果它们具有相同的字段 . 但是,在引擎盖下,您定义的类型和输入将变为非常不同的对象类,每个类具有不同的属性和方法 . 有一些特定于GraphQLObjectType
(如接受参数)的功能在GraphQLInputObjectType
上不存在 - 反之亦然 .试图用来代替另一个有点像试图在圆孔中放一个方形钉 . “我不知道为什么我需要一个圆圈 . 我有一个正方形 . 它们都有一个直径 . 为什么我需要两个?”
除此之外,将类型和输入分开是一个很好的实际原因 . 这是因为在很多情况下,您将在输入上不会暴露的类型上暴露大量字段 .
例如,您的类型可能包含实际上是基础数据组合的派生字段 . 或者它可能包括与其他数据关系的字段(如
User
上的friends
字段) . 在这两种情况下,它都不会作为某个字段的参数提交 . 同样,您可能有一些输入字段,您不希望在其对应的类型上公开(想到一个password
字段) .是的你可以:
输入对象类型上的字段本身可以引用输入对象类型,但不能在模式中混合输入和输出类型 . 输入对象类型也不能在其字段上包含参数 .
除了普通类型之外,还要定义输入类型 . 通常它们会有一些差异,例如输入不会有id或createdAt字段 .