如何管理可以在输出类型中为空的 GraphQL 子对象类型?
How to manage GraphQL child objectType that can be nullable in an output type?
我正在设置一个 nodeJS GraphQL API 并且我正在试验关于我的一种资源输出类型的阻塞点。
该特征是一个包含三个不同级别的表单:
- 级别 1- formTemplate
- 级别 2- formItems (templateId, type (video, image, question) - 与 formTemplate 的 1-N 关系)
- 3 级- formQuestions(与 formItem 的 0-1 关系当且仅当 formItems.type 是 'question')
我的 GraphQL 资源正在 returning 数据库中的所有模板,因此它是一个数组,对于每个模板 returning 他的所有项目和 "question" 需要的每个类型的项目return 包含相关问题的数组。
我的问题是:我真的不知道如何 return 类型不同于 "question" 的 formItems 的空对象类型,或者对于这种类型是否有更好的方法情况
我尝试查看 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": {}
}
]
}
]
}
}
我会设计您的 "level 2" 项目,以便 "type" 属性 对应于实际的 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,您可以类似地使用它来挑选特定于其他类型表单项的字段。
谢谢大卫的回答!
我已经弄清楚如何使用似乎最适合此用例的内联片段和 UnionType 来解决我的问题。这是代码:
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
}
}
}
}
}
我正在设置一个 nodeJS GraphQL API 并且我正在试验关于我的一种资源输出类型的阻塞点。
该特征是一个包含三个不同级别的表单:
- 级别 1- formTemplate
- 级别 2- formItems (templateId, type (video, image, question) - 与 formTemplate 的 1-N 关系)
- 3 级- formQuestions(与 formItem 的 0-1 关系当且仅当 formItems.type 是 'question')
我的 GraphQL 资源正在 returning 数据库中的所有模板,因此它是一个数组,对于每个模板 returning 他的所有项目和 "question" 需要的每个类型的项目return 包含相关问题的数组。
我的问题是:我真的不知道如何 return 类型不同于 "question" 的 formItems 的空对象类型,或者对于这种类型是否有更好的方法情况
我尝试查看 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": {}
}
]
}
]
}
}
我会设计您的 "level 2" 项目,以便 "type" 属性 对应于实际的 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,您可以类似地使用它来挑选特定于其他类型表单项的字段。
谢谢大卫的回答!
我已经弄清楚如何使用似乎最适合此用例的内联片段和 UnionType 来解决我的问题。这是代码:
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
}
}
}
}
}