繁体   English   中英

盖茨比中的一对多关系

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM