一对多的关系

问题描述 投票:1回答:1

使用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参照 外键部分:

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个回答
1
投票

中解释得更好。本节 的文档,实现外键关系的方式根据你如何定义类型而不同。只有当你使用自动类型推理时,你才会使用 ___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});
© www.soinside.com 2019 - 2024. All rights reserved.