我正在设置一个nodeJS GraphQL API,并且正在尝试针对一种资源输出类型的阻塞点。
此功能是包含三个不同级别的表单:
我的GraphQL资源正在返回数据库中的所有模板,因此,这是一个数组,每个模板都将返回其所有项目,并且每个“问题”类型的项目都需要返回一个包含相关问题的数组。
我的问题是:我真的不知道如何为formItems返回一个空对象类型,其中type与“ question”不同,或者对于这种情况是否有更好的方法
我尝试查看GraphQL指令和内联片段,但我认为它确实需要由后端管理,因为它对API使用者是透明的。
const formTemplate = new GraphQLObjectType({
name: 'FormTemplate',
fields: () => {
return {
id: {
type: new GraphQLNonNull(GraphQLInt)
},
authorId: {
type: new GraphQLNonNull(GraphQLInt)
},
name: {
type: new GraphQLNonNull(GraphQLString)
},
items: {
type: new GraphQLList(formItem),
resolve: parent => FormItem.findAllByTemplateId(parent.id)
}
}
}
})
const formItem = new GraphQLObjectType({
name: 'FormItem',
fields: () => {
return {
id: {
type: new GraphQLNonNull(GraphQLInt)
},
templateId: {
type: new GraphQLNonNull(GraphQLInt)
},
type: {
type: new GraphQLNonNull(GraphQLString)
},
question: {
type: formQuestion,
resolve: async parent => FormQuestion.findByItemId(parent.id)
}
}
}
})
const formQuestion= new GraphQLObjectType({
name: 'FormQuestion',
fields: () => {
return {
id: {
type: new GraphQLNonNull(GraphQLInt)
},
itemId: {
type: new GraphQLNonNull(GraphQLInt)
},
type: {
type: new GraphQLNonNull(GraphQLString)
},
label: {
type: new GraphQLNonNull(GraphQLString)
}
}
}
})
我的GraphQL请求:
query {
getFormTemplates {
name
items {
type
question {
label
type
}
}
}
}
我期望的是
{
"data": {
"getFormTemplates": [
{
"name": "Form 1",
"items": [
{
"type": "question",
"question": {
"label": "Question 1",
"type": "shortText"
},
{
"type": "rawContent"
"question": {}
}
]
}
]
}
}
答案 0 :(得分:0)
我将设计您的“级别2”项,以便“类型”属性对应于实际的GraphQL类型,并实现一个公共接口。另外,通常,我会设计架构,使其具有到相邻项目的实际链接,而不是其标识符。
因此,如果每个表单项都可能具有关联的模板,则可以将其设为GraphQL interface:
interface FormItem {
id: ID!
template: FormTemplate
}
然后,您可以为三种商品提供三种不同的类型
# Skipping VideoItem
type ImageItem implements FormItem {
id: ID!
template: FormTemplate
src: String!
}
type QuestionItem implements FormItem {
id: ID!
template: FormTemplate
questions: [FormQuestion!]!
}
您描述的其他类型是:
type FormTemplate {
id: ID!
author: Author!
name: String!
items: [FormItem!]!
}
type FormQuestion {
id: ID!
question: Question
type: String!
label: String!
}
另一个棘手的事情是,由于并非所有表单项都是问题,因此必须特别提到您对查询中的问题感兴趣,以获得特定于问题的字段。您的查询可能看起来像
query {
getFormTemplates {
name
items {
__typename # a GraphQL builtin that gives the type of this object
... on Question {
label
type
}
}
}
}
... on Question
语法是inline fragment,您可以类似地使用它来选择特定于其他类型表单项的字段。
答案 1 :(得分:0)
谢谢大卫的回答!
我已经弄清楚了如何使用似乎最适合此用例的内联片段和UnionTypes解决我的问题。这是代码:
const formItemObjectType = new GraphQLUnionType({
name: 'FormItemObject',
types: [formItemContent, formItemQuestion],
resolveType(parent) {
switch (parent.type) {
case ('question'): return formItemQuestion
default: return formItemContent
}
}
})
和使用内联片段的GraphQL查询:
query {
getFormTemplates {
name
items {
...on FormItemContent {
type,
meta
}
...on FormItemQuestion {
type,
meta,
question {
label
}
}
}
}
}