GraphQL 忽略了一些(但不是全部)任意分配的 markdown frontmatter 数据

GraphQL ignores some (but not all) arbitrarily assigned markdown frontmatter data

第一次尝试 Gatsby,很高兴。但是我 运行 遇到了一个 st运行ge GraphQL 问题:

我正在使用 gatsby-source-filesystem 和 gatsby-t运行sformer-remark 插件从降价文件中提取内容。

前言数据在所有这些中都不相同(title除外)。有些有一个 date 字符串(博客文章),同样有一个 tag 数组,有些有一个 gallery 对象。

现在的问题是,一些这种任意分配的 frontmatter 数据在 GraphQL 中可用,而另一些则不可用。例如,如果我尝试查询日期,我总是得到 "GraphQL Error Unknown field date on type frontmatter_2"。而如果我查询标签,我会得到那些包含一个标签的项目的标签数组,而 tags: null 则为那些不包含标签的项目。

这里有什么问题?我怎样才能始终获得 null 作为节点中不存在的字段的值?

可能值得注意的是,此行为会根据我的降价文件的目录结构而变化。如果我四处移动它们,GraphQL 中的一些 frontmatter 字段将变得可用,而以前这些字段是不可用的,反之亦然。还会发生在通过 HMR 推送一些代码更改后,一些字段变得可用 - 但在我重新启动 Gatsby 之后,尽管没有触及中间的代码,它们又消失了。

非常感谢您的帮助!

编辑:

经过一段时间的努力没有成功,我求助于确保所有 markdown frontmatter 具有相同类型的相同字段。

我猜

TODO link to docs on auto-inferring types/fields.

部分documentation是关于这个问题的。

当我有更多时间时,我想了解更多关于 GraphQL 及其在 Gatsby 中的工作原理。任何指点表示赞赏。

您可能遇到了 this 错误,有时 GraphQL 似乎遗漏了稀疏填充的字段。

但是,要回答您的具体问题,您如何才能确保始终为空字段获得 null。您可以使用 onCreateNode 挂钩来做到这一点。每个节点都会调用此挂钩。

类似于以下伪代码的内容将实现您的目标:

exports.onCreateNode = ({node, getNode, boundActionCreators}) => {
  const { createNodeField } = boundActionCreators

  if (_.get(node, 'internal.type') === `MarkdownRemark`) {

    // Repeat this for each field
    createNodeField({
      node,
      name: 'date',
      value: _.get(node, 'frontmatter.date', 'default date'),
    })

  }
}

这会将值从 frontmatter 复制到 fields 并确保它们始终存在并带有一些默认值(如果它们不存在)。您可以在 node.internal.type 上添加测试以过滤特定节点类型

注意:这是完全未经测试的,即兴的伪代码,使用风险自负!