【问题标题】:One-to-many relationship in gatsby盖茨比中的一对多关系
【发布时间】:2020-05-14 00:52:37
【问题描述】:

使用 Gatsby.js,我想将一些静态文件转换为层次结构。这种层次结构的一个方面是一个“可执行文件”有许多由该可执行文件生成的文件。我的可执行文件的 GraphQL 架构是:

exports.createSchemaCustomization = ({ actions: {createTypes}, schema }) => {
  createTypes([
    schema.buildObjectType({
      name: "CondaExecutable",
      fields: {
        wrappers: "[File]",
        name: "String!",
        path: "String!",
        publicURL: "String!",
      },  
      interfaces: ["Node"],
    }), 
  ])  
}

然后,我想在我的新对象的wrapper 字段中添加多个文件,我尝试在createPages 中执行此操作,参考foreign key section in the Gatsby docs

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。无论如何,我并不奇怪这是错误的,因为我真的不知道我在这里做什么。

如何在我自己的自定义类型和许多 Files 之间建立关系?

【问题讨论】:

    标签: javascript graphql gatsby


    【解决方案1】:

    正如文档的this section 中更好地解释的那样,实现外键关系的方式因定义类型的方式而异。仅当您使用自动类型推断时,您才使用 ___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"],
    })
    

    如果您改为一对一关系,您的解析函数将如下所示:

    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});
    

    【讨论】:

      猜你喜欢
      • 2020-07-20
      • 1970-01-01
      • 2020-12-16
      • 2020-10-16
      • 2019-08-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2022-08-19
      相关资源
      最近更新 更多