Apollo/GraphQl - 类型必须是输入类型

Ivo*_*Ivo 7 meteor apollo graphql

当我在学习过程中将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

}
Run Code Online (Sandbox Code Playgroud)

然后定义输入和加载,依此类推......

为此,我想要一个变种来保存"计算",所以在同一个文件中我有这个:

type Mutation {
    saveCalculation(data: CalculationData!, name: String!): Calculation
}
Run Code Online (Sandbox Code Playgroud)

我的解析器如下:

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')
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我的变异如下:从'graphql-tag'导入gql;

export const SAVE_CALCULATION = gql`
    mutation saveCalculation($data: CalculationData!, $name: String!){
        saveCalculation(data: $data, name: $name){
            _id
        }
    }
`
Run Code Online (Sandbox Code Playgroud)

最后我使用Mutation组件尝试保存数据:

<Mutation mutation={SAVE_CALCULATION}>
    {(saveCalculation, { data }) => (
        <div onClick={() => saveCalculation({ variables : { data: this.state, name:'name calcul' }})}>SAVE</div>
    }}
</Mutation>
Run Code Online (Sandbox Code Playgroud)

现在我收到以下错误:

[GraphQL错误]:消息:Mutation.saveCalculation(data :)的类型必须是输入类型但得到:CalculationData!.,Location:undefined,Path:undefined

从我的研究和其他一些SO帖子中,除了Query类型之外我还应该定义输入类型,但是输入类型只能是标量类型,但我的模式依赖于其他模式(这不是标量).我可以根据其他输入类型创建输入类型,等等,当最后一个只有标量类型时?我有点失落,因为它似乎有很多冗余.非常感谢对最佳实践的一些指导.我确信Apollo/graphql可以在我的项目中为我提供很好的帮助,但我不得不承认,当Schemas有点复杂时,它比我想要的更复杂.在线示例通常坚持使用String和Boolean.

Dan*_*den 6

从规格:

字段可以接受参数来配置其行为.这些输入通常是标量或枚举,但有时需要表示更复杂的值.

GraphQL输入对象定义一组输入字段; 输入字段是标量,枚举或其他输入对象.这允许参数接受任意复杂的结构.

换句话说,您不能使用常规GraphQLObjectTypes作为GraphQLInputObjectType字段的类型- 您必须使用另一个GraphQLInputObjectType.

使用SDL编写模式时,必须创建Load类型和LoadInput输入似乎是多余的,特别是如果它们具有相同的字段.但是,在引擎盖下,您定义的类型和输入将变为非常不同的对象类,每个类具有不同的属性和方法.有一种特定于GraphQLObjectType(如接受参数)的功能,它们不存在GraphQLInputObjectType- 反之亦然.

试图用来代替另一个有点像试图在圆孔中放一个方形钉."我不知道为什么我需要一个圆圈.我有一个正方形.它们都有直径.为什么我需要两个?"

除此之外,将类型和输入分开是一个很好的实际原因.这是因为在很多情况下,您将在输入上不会暴露的类型上暴露大量字段.

例如,您的类型可能包含实际上是基础数据组合的派生字段.或者它可能包括与其他数据关系的friends字段(如a上的字段User).在这两种情况下,将这些字段作为某些字段的参数提交的数据的一部分是没有意义的.同样,您可能有一些输入字段,您不希望在其类型对应项上公开(一个password字段会浮现在脑海中).

  • @YanickRochon GraphQL 具有由“type”关键字指定的[对象类型](http://spec.graphql.org/June2018/#sec-Objects)和[输入对象类型](http://spec.graphql.org/ June2018/#sec-Input-Objects)由“input”关键字设计。前者用于输出,后者用于输入。 (3认同)