node.js - 为什么子字段在不同的接口时会发生冲突?
问题描述
我正在尝试trivia
使用 GraphQL (Apollo Server) 查询单个 MongoDB 文档 ( ),但其中一个文档字段有问题。
LightningRoundQuestion.answer
并且PictureRoundPicture.answer
应该返回一个String
,并且MultipleChoiceRoundQuestion.answer
应该返回一个Int
。查看架构:
schema
const typeDefs = gql`
# ROOT TYPES ==================================================
type Query {
trivia(_id: String!): Trivia
}
# INTERFACES ==================================================
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]
}
type PictureRound implements Round {
type: String!
theme: String!
pointValue: Int!
pictures: [PictureRoundPicture]
}
# QUERY TYPES =================================================
type LightningRoundQuestion {
question: String!
answer: String!
}
type MultipleChoiceRoundQuestion {
question: String!
options: [String!]!
answer: Int!
}
type PictureRoundPicture {
url: String!
answer: String!
}
type Trivia {
_id: String!
createdAt: String!
triviaId: String!
triviaPin: String!
host: String!
rounds: [Round]!
tieBreaker: TieBreaker!
}
type TieBreaker {
question: String
answer: Int
}
`
resolvers & server
const resolvers = {
Query: {
trivia: async (root, { _id }) => {
return triviaCollection.findOne(ObjectId(_id))
}
},
Round: {
__resolveType(obj) {
if (obj.type === 'multipleChoice') {
return 'MultipleChoiceRound'
} else if (obj.type === 'lightning') {
return 'LightningRound'
} else if (obj.type === 'picture') {
return 'PictureRound'
}
}
}
}
const server = new ApolloServer({ typeDefs, resolvers })
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`)
})
query
query {
trivia(_id: "5e827a4e1c9d4400009fea32") {
_id
createdAt
triviaId
triviaPin
host
rounds {
... on LightningRound {
questions {
question
answer
}
}
... on MultipleChoiceRound {
questions {
question
options
answer
}
}
... on PictureRound {
pictures {
url
answer
}
}
}
}
}
我收到错误消息:
"message": "Fields \"questions\" conflict because subfields \"answer\" conflict because they return conflicting types \"String!\" and \"Int!\". Use different aliases on the fields to fetch both if this was intentional."
不太确定下一步该做什么,我查看了 Apollo 文档中的 Alias,但那里几乎没有帮助。
解决方案
这在使用抽象类型时有点棘手,是 GraphQL 如何处理合并字段选择的结果。归结为,如果您在同一选择集中多次请求具有相同名称(或别名)的字段,则该字段必须返回相同的类型。在上面的模式中,它没有——问题可能有类型[LightningRoundQuestion]
,[PictureRoundPicture]
等等。
有关详细说明,请参阅规范的此部分。
有两种解决方法。在客户端,您可以使用别名来确保 GraphQL 不会首先尝试合并字段:
rounds {
... on LightningRound {
lightningQuestions: questions {
question
answer
}
}
... on MultipleChoiceRound {
multipleChoiceQuestions: questions {
question
options
answer
}
}
}
当您无法更改架构时,这是您最好的选择。但是,您也可以只更改服务器端的字段名称以获得更好的客户端 DX。
rounds {
... on LightningRound {
lightningQuestions {
question
answer
}
}
... on MultipleChoiceRound {
multipleChoiceQuestions {
question
options
answer
}
}
}
请注意,我们不必使用type
,theme
或pointValue
因为这些字段在您的所有实现类型中具有相同的类型。
推荐阅读
- xamarin.forms - Xamarin.Forms:列表变得比列表视图中的项目长
- python - Django嵌套重组
- java - android.app.ActivityManager.AppTask 访问静态类的非静态方法
- r - 上传文件并在闪亮中使用summarytools
- arrays - 如何使用 Laravel 将 JSON 元素保存为数据库中的记录?
- reactjs - 无法读取未定义 npm ERR 的属性“拆分”!代码生命周期
- c# - 按下 Enter 键时,具有 Janus Gridex 的 WinForm 挂起/冻结
- node.js - 配置 PollyJS 以忽略某些请求
- c# - C# 中的冗余存储或 linq 语句?
- html - how to change the font size of the text on my button (HTML/CSS)