如何向 GraphQL 添加 'resolveType'?



我正在尝试使用GraphQL查询单个MongoDB文档(trivia(,但是其中一个文档字段遇到问题。它是应该返回对象数组(LightningRoundMultipleChoiceRound(的trivia.rounds字段。

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
}
}
}
}

我不断收到错误:

"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."

我不明白resolveTypeisTypeOf是什么意思.我已经在其他问题中看到了这一点,但不知道在我的设置中实现什么。如果我删除rounds字段,db 连接和解析器工作正常,所以它在那里......

GraphQL 支持两种抽象类型——联合和接口。抽象类型是表示两个或多个可能类型的类型。抽象类型允许您为字段指定单个类型,该类型可能是运行时(即执行查询时(的几种可能类型之一。执行查询时,GraphQL 永远不能返回抽象类型——相反,在执行查询时,必须将该类型解析为可能的类型之一。

如果字段返回列表,则列表中每个项目的类型将单独解析。此类型解析发生在解析每个项目上的任何字段之前。更重要的是,解析的类型决定了首先需要解析哪些字段。

在上面的例子中,你已经定义了一个抽象类型(接口Round(和几种可能的类型(LightningRoundMultipleChoiceRound等(。但是,您还没有告诉 GraphQL 如何确定RoundLightningRoundMultipleChoiceRound还是其他可能的类型。这就是提供resolveType功能的目的。通常为架构中的每个抽象类型定义一个resolveType函数。假设您使用的是graphql-toolsapollo-server,您可以通过用于定义解析器的同一解析器映射对象提供此函数:

const resolvers = {
Round: {
__resolveType: (round) => {
// your code here
},
},
}

resolveType将传递 Round 对象(即rounds解析器返回的对象之一(——您可以使用该值来确定它是哪种 Round。根据您的代码,我猜您会使用type属性来区分不同类型的类型。resolveType应返回一个字符串值,其中包含匹配类型的名称。所以它可以像这样简单:

const resolvers = {
Round: {
__resolveType: (round) => {
return round.type
},
},
}

有关其他示例,请参阅文档。

isTypeOf是解析类型的另一种方法。您可以为每个可能的类型定义一个isTypeOf函数,而不是为抽象类型定义resolveType函数。此函数返回 true 或 false 以指示它收到的对象是否实际上是类型。isTypeOf有用途,但通常更容易使用resolveType

最新更新