[英]How to add a `resolveType` to GraphQL?
I am trying to query a single MongoDB document ( trivia
) using GraphQL, but am having trouble with one of the document fields.我正在尝试使用 GraphQL 查询单个 MongoDB 文档( trivia
),但其中一个文档字段有问题。 It's the trivia.rounds
field that should return an array of objects (either LightningRound
or MultipleChoiceRound
). trivia.rounds
字段应该返回一个对象数组( LightningRound
或MultipleChoiceRound
)。
schema.graphql
type Trivia {
_id: String!
createdAt: String!
rounds: [Round]!
}
interface Round {
type: String!
theme: String!
pointValue: Int!
}
type LightningRound implements Round {
type: String!
theme: String!
pointValue: Int!
questions: [LightningRoundQuestion]
}
type MultipleChoiceRound implements Round {
type: String!
theme: String!
pointValue: Int!
questions: [MultipleChoiceRoundQuestion]
}
// ...
trivia.js // resolver
require('dotenv').config()
const { ObjectId } = require('mongodb')
const trivia = (app) => {
return async (root, { _id }) => {
return app
.get('db')
.collection(process.env.DB_COLLECTION_TRIVIA)
.findOne(ObjectId(_id))
}
}
module.exports = {
trivia
}
graphql query
query {
trivia(_id: "5e827a4e1c9d4400009fea32") {
_id
createdAt
rounds {
__typename
... on MultipleChoiceRound {
type
theme
}
... on PictureRound {
type
theme
}
... on LightningRound {
type
theme
}
}
}
}
I keep getting the error:我不断收到错误:
"message": "Abstract type \"Round\" must resolve to an Object type at runtime for field \"Trivia.rounds\" with value { questions: [[Object], [Object]] }, received \"undefined\". Either the \"Round\" type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function."
I don't understand what it means by resolveType
or isTypeOf
.我不明白resolveType
或isTypeOf
是什么意思。 I've seen this in other questions, but have no clue what to implement in my setup.我在其他问题中看到了这一点,但不知道在我的设置中实现什么。 The db connection and resolver works fine if I remove the rounds
field, so it's something there...如果我删除rounds
字段,数据库连接和解析器工作正常,所以它在那里......
GraphQL supports two kinds of abstract types -- unions and interfaces. GraphQL 支持两种抽象类型——联合和接口。 An abstract type is a type that represents two or more possible types.抽象类型是表示两种或多种可能类型的类型。 Abstract types allow you to specify a single type for your field that could be one of several possible types at runtime (ie when the query is executed).抽象类型允许您为字段指定单一类型,该类型可能是运行时(即执行查询时)的几种可能类型之一。 When executing a query, GraphQL can never return an abstract type -- instead, the type has to be resolved into one of the possible types when the query is executed.执行查询时,GraphQL 永远不能返回抽象类型——相反,执行查询时必须将类型解析为可能的类型之一。
If a field returns a list, then the type for each item in the list will resolved separately.如果一个字段返回一个列表,那么列表中每个项目的类型将单独解析。 This type resolution happens before any of the fields on each item are resolved.此类型解析发生在解析每个项目上的任何字段之前。 More to the point, the type that's resolved determines which fields need to be resolved in the first place.更重要的是,解析的类型决定了首先需要解析哪些字段。
In your example above, you've defined an abstract type (the interface Round
) and several possible types for it ( LightningRound
, MultipleChoiceRound
, etc.).在上面的示例中,您已经定义了一个抽象类型(接口Round
)和几种可能的类型( LightningRound
、 MultipleChoiceRound
等)。 However, you have not told GraphQL how to determine whether a Round
is a LightningRound
, a MultipleChoiceRound
or another possible type.但是,您还没有告诉 GraphQL 如何确定Round
是LightningRound
、 MultipleChoiceRound
还是其他可能的类型。 This is the purpose of providing a resolveType
function.这是提供resolveType
function 的目的。 You typically define a resolveType
function for each abstract type in your schema.您通常为架构中的每个抽象类型定义一个resolveType
function。 Assuming you're using graphql-tools
or apollo-server
, you provide this function through the same resolver map object you use to define your resolvers:假设您使用的是graphql-tools
或apollo-server
,您通过相同的解析器 map object 提供此 function 来定义您的解析器:
const resolvers = {
Round: {
__resolveType: (round) => {
// your code here
},
},
}
resolveType
will be passed the Round object (ie one of the objects returned by your rounds
resolver) -- you can use that value to determine what kind of Round it is. resolveType
将通过 Round object(即您的rounds
解析器返回的对象之一)——您可以使用该值来确定它是哪种 Round。 Based on your code, I'm guessing you'd use the type
property to differentiate between the different types.根据您的代码,我猜您会使用type
属性来区分不同的类型。 resolveType
should return a string value with the name of the matched type. resolveType
应该返回一个带有匹配类型名称的字符串值。 So it could be as simple as:所以它可以很简单:
const resolvers = {
Round: {
__resolveType: (round) => {
return round.type
},
},
}
For additional examples, see the docs .有关其他示例,请参阅文档。
isTypeOf
is an alternative approach to resolving the type. isTypeOf
是解析类型的另一种方法。 Instead of defining a resolveType
function for the abstract type, you can define a isTypeOf
function for each possible type.您可以为每个可能的类型定义一个isTypeOf
function,而不是为抽象类型定义一个resolveType
function。 This function returns true or false to indicate whether the object it received is in fact the type.这个 function 返回 true 或 false 以表明它收到的 object 是否实际上是该类型。 There are uses for isTypeOf
, but it's typically easier to just use resolveType
instead. isTypeOf
有一些用途,但通常只使用resolveType
会更容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.