Gatsby: 问题:如何基于gatsby-source-filesystem名称进行查询?

创建于 2017-07-27  ·  20评论  ·  资料来源: gatsbyjs/gatsby

我有多个用于不同页面类型的文件夹。 就是包含markdown文件的type1,type2等。

pages
   --type1
   --type2

每个文件夹中的文件都使用gatsby-transformer-remark
我只想查询type1,type2等的内容。
例如,我想要一个type1列表页面,其中包含所有type1页面的列表。

gatsby-config.js

   {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/pages/type1`,
        name: 'type1',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/pages/type2`,
        name: 'type2',
      },
    },

我的假设是您可以基于name属性进行查询。

就像是:

{
  someQueryForGatsbySourceFilesystem(
    filter: {
      name: {
        eq: "type1"
      }
    }
  ) {
    edges {
      node {
        childMarkdownRemark {
          html
        }
      }
    }
  }
}

我尝试了所有不同的查询,例如allSite和allFile,但找不到解决方案。
我也试过

  allSitePlugin(filter: {
    pluginOptions: {
      name: {
        eq: "type1"
      }
    }
  })

这似乎没有返回我可以用来渲染内容的东西:

"Cannot query field \"childMarkdownRemark\" on type \"SitePlugin\".",

你会怎么做? 使用allFile并根据路径名进行过滤(即与文件夹type1和markdown扩展名匹配的正则表达式)?

 allFile(
  filter: {
    absolutePath:{regex:"/(type1)\/.*\\.md$/"}
  }
) {...}
question or discussion

最有用的评论

@ tsiq-swyx我正在使用类似的方法将collection字段从File传递到MarkdownRemark

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

  if (_.get(node, 'internal.type') === `MarkdownRemark`) {
    // Get the parent node
    const parent = getNode(_.get(node, 'parent'))

    // Create a field on this node for the "collection" of the parent
    // NOTE: This is necessary so we can filter `allMarkdownRemark` by
    // `collection` otherwise there is no way to filter for only markdown
    // documents of type `post`.
    createNodeField({
      node,
      name: 'collection',
      value: _.get(parent, 'sourceInstanceName'),
    })

regex方法确实有效,但它很脆弱。

所有20条评论

我认为您也可以使用allMarkdownRemark过滤路径:

{
   allMarkdownRemark(
    sort: { order: DESC, fields: [frontmatter___date]},
    filter: {fileAbsolutePath: {regex: "/(type1)/.*\\.md$/"}}
  ) {
      edges {
        node {
          excerpt(pruneLength: 250)
          id
          frontmatter {
            title
            date(formatString: "MMMM DD, YYYY")
            path
          }
        }
      }
    }
}

文件节点的源实例名称设置为sourceInstanceName因此您可以将其用于查询。

使用正则表达式也是一个很好的解决方案,例如我们在gatsbyjs.org上使用了很多。

顺便说一句,如果您还没有使用它,则GraphiQL非常适合探索可用数据。

@KyleAMathews是否可以在allMarkdownRemark查询中使用sourceInstanceName ? 我希望可以像这样为每个markdown节点获取文件节点的sourceInstanceName ,这样我可以将博客文章与项目分开,而无需在文件路径上使用正则表达式。

{
  allMarkdownRemark {
    edges {
      node {
        sourceInstanceName
      }
    }
  }
}

但是GraphQL调试器显示sourceInstanceName不可用。

您如何建议按源类型(例如项目和博客文章)过滤降价页面? 我当前的解决方案是获取每个降价节点的fileAbsolutePath

{
  allMarkdownRemark {
    edges {
      node {
        fileAbsolutePath
      }
    }
  }
}

然后测试它是否包含某些字符串,例如/pages/blog//pages/projects/ 。 但是,如果gatsby站点目录本身的绝对路径本身包含以下字符串之一,则此操作将中断。 在这种情况下,您推荐什么是最佳做法? (对不起,如果我错过了文档中的内容。)

@nwshane只需查询allFile并在那里进行过滤。 您可以按internal.mediaType过滤降价文件。

@KyleAMathews如何将对allFile的查询与对前事的排序结合在一起? 那可能吗?

试图找出类似的东西。

我可以按子文件夹过滤。 但我在allFile中看不到frontmatter allFile

screen shot 2018-02-25 at 8 18 51 p m

更新:

这对我有用。

我在文件夹posts有文件夹pages content ,我的gatsby-config.js指向content

export const query = graphql`
  query IndexQuery {
    allMarkdownRemark(
      filter: { fileAbsolutePath: {regex : "\/posts/"} },
      sort: {fields: [frontmatter___date], order: DESC},
    ) {
      totalCount
      edges {
        node {
          id
          frontmatter {
            title
            slug
            date(formatString: "DD MMMM YYYY")
            category
          }
          excerpt
        }
      }
    }
  }
`;

@lukejanicke自从我上一次更新以来,我深入研究了节点系统。 减价处理程序将解析allFile节点,然后创建新的allMarkdownRemark节点。 因此,正如您所发现的那样,不可能在allFile按frontmatter进行排序,因为它仅在降价解析器启动后才生成。regex有效,但就我的口味而言,它有点脆弱。 我的解决方案是通过onCreateNode钩子将集合名称(在文件系统源插件配置中指定)从文件节点复制到markdown节点。 我前面没有代码来发布示例,但这很快,然后我可以在allMarkdownRemark中有一个可以过滤的字段。

@KyleAMathews建议的另一种可能性(在我的情况下,源名称为projects

allFile(filter: {internal: {mediaType: {eq: "text/markdown"}}, sourceInstanceName: {eq: "projects"}}) {
  edges {
    node {
      childMarkdownRemark {
        frontmatter {
            ...
        }
      }
    }
  }
}

@gbouteiller是的,这将获得frontmatter并允许一个人按sourceInstanceName进行过滤。 麻烦的是,您不能使用这种方法frontmatter的任何内容进行排序。 似乎人们在这里谈论博客文章,通常按日期排序。 该日期通常存储在frontmatter

有没有办法通过某种东西做frontmatter和过滤器由sourceInstanceName默认。 没有将sourceInstanceNameFile节点复制到markdownRemark节点。 唯一的选择是使用正则表达式或按照我之前的文章复制一些数据。

如果不需要排序(在许多情况下可能是正确的),则您的方法很有意义。 我还没有意识到childMarkdownRemark可以作为file上的一个字段使用,这非常有用,感谢您的分享。

遇到了这个问题,对于“ name”字段不能与markdownRemark配合使用感到非常失望。 我们可以做些小事来传递这些信息吗?

编辑:经过一番混乱后,我意识到id字段公开了路径,您可以基于此进行过滤:

query AllQuery {
    DSes: allMarkdownRemark(
      limit: 3
      filter: { id: { regex: "/_design-systems/" } }
    ) {
      edges {
        node {
          frontmatter {
            title
            date
            company
            link
            image
            description
          }
          fields {
            slug
          }
        }
      }
    }

    Articles: allMarkdownRemark(
      limit: 3
      filter: { id: { regex: "/_articles/" } }
    ) {
      edges {
        node {
          frontmatter {
            title
            date
            company
            link
            image
            description
          }
          fields {
            slug
          }
        }
      }
    }
  }

源文件系统中的name字段对于gatsby-transformer-remark仍然没有任何作用,因为gatsby-transformer-remark从来没有改善过dx作为可查询/可过滤字段存在没有gatsby-source-filesystem

@ tsiq-swyx我正在使用类似的方法将collection字段从File传递到MarkdownRemark

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

  if (_.get(node, 'internal.type') === `MarkdownRemark`) {
    // Get the parent node
    const parent = getNode(_.get(node, 'parent'))

    // Create a field on this node for the "collection" of the parent
    // NOTE: This is necessary so we can filter `allMarkdownRemark` by
    // `collection` otherwise there is no way to filter for only markdown
    // documents of type `post`.
    createNodeField({
      node,
      name: 'collection',
      value: _.get(parent, 'sourceInstanceName'),
    })

regex方法确实有效,但它很脆弱。

@chmac这非常聪明,它可以工作,谢谢您分享您的解决方案。 @KyleAMathews对标记您(如果还有其他人标记,gatsby-source-filesystem是否可以这种方式工作(将sourceInstanceName传递给节点字段或其他字段)?

@ tsiq-swyx我不确定100%,但是我想这可能是一个相当简单的请求! ;-)

我认为gatsby维护者对这些事情有强烈的看法,因此我认为在发送未经请求的PR之前值得讨论:)

好的,我可以使用它,但是我的createPages导出仅使用一个模板

令人惊讶的是,使用gatsby-source-filesystem完全不需要graphql中的AllFile。 这可能会带来混乱,并且不会在文档中反映出来。
我在用
const { createPage } = actions const result = await graphql(` query { allMarkdownRemark { edges { node { fields { slug } frontmatter { lang } } } } } `)
并且它可以毫无问题地创建页面。 但是不确定是否相同的原理适用于gatsby-source-git

谢谢@chmac

我必须基于gatsby-source-filesystem名称创建页面...

所以这是我的解决方案:

const { createFilePath } = require("gatsby-source-filesystem")

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

  if (node.internal.type === `Mdx` && getNode(node.parent).sourceInstanceName === "careers") {
    const value = createFilePath({ node, getNode })

    createNodeField({
      name: "slug",
      node,
      value: `/careers${value}`
    })
  }
}

这很有趣,从来没有找到这样的选项node.parent存在

2020年4月27日星期一,诺曼·古尔[email protected]写道:

谢谢@chmac https://github.com/chmac

我必须基于gatsby-source-filesystem名称创建页面...

所以这是我的解决方案:

const {createFilePath} = require(“ gatsby-source-filesystem”)
exports.onCreateNode =({{节点,操作,getNode})=> {
const {createNodeField} =操作

如果(node.internal.type === Mdx && getNode(node.parent).sourceInstanceName ===“职业”){
const value = createFilePath({node,getNode})

createNodeField({
  name: "slug",
  node,
  value: `/careers${value}`
})

}
}

-
您收到此邮件是因为您发表了评论。
直接回复此电子邮件,在GitHub上查看
https://github.com/gatsbyjs/gatsby/issues/1634#issuecomment-619670883
或退订
https://github.com/notifications/unsubscribe-auth/AAEQPFX6KR7NUIY33Q7V4MDROTS7PANCNFSM4DUUPK6A

在阅读了此线程之后,我处于一种我认为是相当普遍的情况下; 我认为,最好的非hacky解决方案是:

{
  allMarkdownRemark(filter: {fileAbsolutePath: {regex: "/projects/"}}) {
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

我的projects类型的内容在/content/projects/

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

jimfilippou picture jimfilippou  ·  3评论

benstr picture benstr  ·  3评论

totsteps picture totsteps  ·  3评论

kalinchernev picture kalinchernev  ·  3评论

3CordGuy picture 3CordGuy  ·  3评论