GraphQL :对象名称在解析器中定义,但不在模式中 [英] GraphQL : the object name is defined in resolvers, but not in schema
问题描述
我想使用 graphql 定义一个突变.
I want to define a mutation using graphql.
我的突变正在获取一个对象作为参数.所以我在架构和解析器中使用 GraphQLObjectType 定义了新对象.
My mutation is getting an object as argument. So I defined the new Object in the schema and in the resolver using GraphQLObjectType.
但是我收到此错误:
错误:在解析器中定义了协议名称,但在架构中未定义
Error: Agreement.name defined in resolvers, but not in schema
有什么想法吗?
这是我的架构定义
const typeDefs = `
type Agreement {
id: Int
}
type Mutation {
agreementsPost(agreement: Agreement) : String
}
`;
这是我的解析器:
const appResolvers = {
Agreement: new GraphQLObjectType({
name: 'Agreement',
fields: {
id: { type: GraphQLInt },
}
}),
Mutation: {
agreementsPost(root, args) {
return axios.post("....").then(res => res.data);
},
}
推荐答案
这里有几个问题需要解决.首先,要将对象用作参数,您必须在架构中将其定义为 input
(或 GraphQLInputObjectType
)——您不能使用常规的 type
(或 GraphQLObjectType
)作为参数.
Couple of things to fix here. First, to use an object as an argument, you have to define it as an input
(or GraphQLInputObjectType
) in your schema -- you cannot use a regular type
(or GraphQLObjectType
) as an argument.
所以你的类型定义需要看起来像这样:
So your type definitions need to look something like this:
type Mutation {
agreementsPost(agreement: Agreement): String
}
input Agreement {
id: Int
}
如果您已经有 Agreement
类型,则需要将输入命名为其他名称.将 Input
附加到您的类型名称是一个很好的约定:
If you already have an Agreement
type, you'll need to name your input something else. It's a good convention to just append Input
to whatever your type name is:
type Mutation {
agreementsPost(agreement: AgreementInput): String
}
type Agreement {
id: Int
}
input AgreementInput {
id: Int
}
这应该足以让您将 AgreementInput
对象作为参数传递给您的变更.您不需要向解析器添加 Agreement
或 AgreementInput
(实际上,GraphQL 不会解析"输入,因此无法为输入添加解析器).
This should be sufficient to allow you to pass in an AgreementInput
object as an argument to your mutation. You don't need to add Agreement
or AgreementInput
to your resolvers (in fact, inputs are not "resolved" by GraphQL, so adding a resolver for an input is not possible).
也就是说,您的解析器对象不需要包含 graphql
包提供的任何类型构造函数——Apollo 从您的解析器和类型构造一个 GraphQLSchema
对象调用 makeExecutableSchema
时的定义.
That said, your resolvers object should not need to incorporate any of the type constructors provided by the graphql
package -- Apollo constructs a GraphQLSchema
object from your resolvers and type definitions for you when you call makeExecutableSchema
.
如果您的类型定义包括 Foo
和 Bar
类型,您的 resolvers
对象可能如下所示:
If your type definitions include the types Foo
and Bar
, your resolvers
object might look something like this:
const resolvers = {
Foo: {
someFooProperty: (foo, args, context, info) => {}
},
Bar: {
someBarProperty: (bar, args, context, info) => {}
someOtherBarProperty: (bar, args, context, info) => {}
},
Query: {
someQuery: (root, args, context, info) => {}
},
Mutation: {
someMutation: (root, args, context, info) => {}
},
}
注意 resolvers
对象中的每个属性如何匹配您的架构中定义的类型之一(包括查询和变异).每个属性的值本身就是一个对象,每个属性都映射到为该特定类型定义的字段之一.每个字段的值是您的 resolve
函数.
Notice how each property in the resolvers
object matches one of the types defined in your schema (including Query and Mutation). The value of each of those properties is itself an object, with each property mapping to one of the fields defined for that particular type. Each field's value is your resolve
function.
您看到的错误的原因是您已经有效地告诉 makeExecutableSchema
将解析器添加到协议类型的两个字段 - name
和 >fields
- 根据您的类型定义,它们实际上都不在您的架构中.
The reason for the error you're seeing is that you've effectively told makeExecutableSchema
to add resolvers to two fields on the Agreement type -- name
and fields
-- neither of which are actually in your schema according to your type definitions.
您可以在此处阅读有关如何使用 Apollo 生成架构的更多信息.您可能会看到通过定义 GraphQLSchema 对象并将其传递给您的中间件,仅使用 GraphQL.js 以编程方式"生成模式的示例.两种方法各有利弊,但使用 makeExecutableSchema
通常更容易且不易出错.无论哪种方式,知道如何以编程方式生成模式是件好事,但您不应将两者混用!
You can read more about how to generate a schema using Apollo here. You may see examples out there of generating a schema "programatically" using just GraphQL.js by defining a GraphQLSchema object and passing that to your middleware instead. There's pros and cons to both approaches, but using makeExecutableSchema
is generally easier and less error-prone. Either way, it's good to know how to generate a schema programatically, but you should not mix the two!
这篇关于GraphQL :对象名称在解析器中定义,但不在模式中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!