[英]One-to-many relationship in gatsby
使用 Gatsby.js,我想将许多 static 文件转换为层次结构。 这种层次结构的一个方面是一个“可执行文件”具有许多由该可执行文件生成的文件。 我的可执行文件的 GraphQL 架构是:
exports.createSchemaCustomization = ({ actions: {createTypes}, schema }) => {
createTypes([
schema.buildObjectType({
name: "CondaExecutable",
fields: {
wrappers: "[File]",
name: "String!",
path: "String!",
publicURL: "String!",
},
interfaces: ["Node"],
}),
])
}
然后,我想将多个文件添加到我的新 object 的wrapper
字段中,我尝试在createPages
中执行此操作,参考Gatsby 文档中的外键部分:
exports.createPages = async ({ graphql, actions, getNode, createContentDigest, createNodeId}) => {
const { createNode, createNodeField, createPage, createParentChildLink } = actions
const result = await graphql(`
{
allFile(filter: {sourceInstanceName: {in: ["Wrappers", "Definitions"]}}) {
edges {
node {
id
relativePath
extension
publicURL
}
}
}
}
`)
await Promise.all(result.data.allFile.edges.map(async ({ node }) => {
// Now create the node for the single file within that package
const exeId = createNodeId(...);
let exe = getNode(exeId);
if (!exe) {
exe = {
id: exeId,
name: stem,
path: node.relativePath.split('.')[0],
publicURL: exeUrl,
parent: versionId,
wrappers: [],
internal: {
type: "CondaExecutable",
contentDigest: node.relativePath
}
};
await createNode(exe);
}
// Link the executable to the wrapper
const wrappers = exe.wrappers || [];
wrappers.push(node.id)
createNodeField({node: exe, name: 'wrappers___NODE', value: wrappers});
}));
}
不幸的是,这段代码不起作用。 我收到错误Cannot return null for non-nullable field File.id
。 无论如何,我并不惊讶这是错误的,因为我真的不知道我在这里做什么。
如何在我自己的自定义类型和许多File
之间建立关系?
正如在文档的本节中更好地解释的那样,实现外键关系的方式因定义类型的方式而异。 仅当您使用自动类型推断时,您才使用___NODE
语法。 如果您在 GraphQL 中定义了自定义类型,而不是使用createTypes()
,则可以为此目的使用@link
指令。
如果您使用第三个选项createTypes()
来定义您的自定义类型,您需要为您的外键实现resolve()
。 在我的一对多情况下,这意味着:
schema.buildObjectType({
name: "CondaExecutable",
fields: {
wrappers: {
type: "[File]",
resolve(source, args, context, info){
return context.nodeModel.getNodesByIds({
ids: source.wrappers, // This matches the name of the field we're currently inside
type: 'File' // This matches the type of the wrappers field
})
}
},
name: "String!",
path: "String!",
publicURL: "String!",
},
interfaces: ["Node"],
})
如果您有一对一的关系,您的解析 function 将如下所示:
resolve(source, args, context, info){
return context.nodeModel.getNodeById({
id: source.wrapper,
type: 'File'
})
}
然后,要链接createPages
中的节点,您不必使用___NODE
语法,但每次添加新子项时都必须使用带有更新数组的createNodeField
:
const wrappers = exe.wrappers || [];
wrappers.push(node.id)
createNodeField({node: exe, name: 'wrappers', value: wrappers});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.