使用 GatsbyJS 的 GraphQL 查询中的范围文件夹结构

Posted

技术标签:

【中文标题】使用 GatsbyJS 的 GraphQL 查询中的范围文件夹结构【英文标题】:Scoping folder structure in GraphQL Queries with GatsbyJS 【发布时间】:2019-07-25 15:32:02 【问题描述】:

我确实有类别、片段和图片。它们都是级联的;典型的亲子关系。并且文件夹结构已经代表了这个层次结构。最后我会更详细地解释我的主要问题。

文件夹结构:

work
├── drawing
│   ├── drawing-1
│   │   ├── image.1.jpg
│   │   ├── image.2.jpg
│   │   ├── image.3.jpg
│   │   ├── image.jpg
│   │   └── index.md
│   └── index.md
├── sculpture
│   ├── gaehnschreier
│   │   ├── image.1.JPG
│   │   ├── image.2.jpg
│   │   ├── image.3.JPEG
│   │   ├── image.4.png
│   │   ├── image.PNG
│   │   └── index.md
│   └── index.md
└── watercolor
    ├── index.md
    ├── portrait-1
    │   ├── image.jpg
    │   └── index.md
    └── portrait-2
        ├── image.jpg
        └── index.md

这是一个简单的投资组合层次结构。 work 是根文件夹,有不同的类别,例如drawing。在里面你会找到代表特定作品的文件夹。每件作品都有一个index.md,其中包含有关该作品的详细信息和多张图片(jpeg、png 等)。


gatsby-config.js:

// ...

  resolve: 'gatsby-source-filesystem',
  options: 
    name: 'work',
    path: `$__dirname/work/`,
  ,
,
// ...

为了解析文件,我使用了gatsby-source-filesystem 插件。所以,我可以通过sourceInstanceName: eq: "work" 查询那个文件夹。


gatsby-node.js:

exports.onCreateNode = ( node, getNode, actions ) => 

  const  createNodeField  = actions

  if (node.internal.type === `Directory`) 

    if (node.sourceInstanceName === `work`) 

      if (!node.relativeDirectory) 
        createNodeField(
          node,   
          name: `workCategory`,
          value: true,  
        )
      
    
  

此代码可帮助我标记类别以供以后使用,例如在概览页面上显示类别列表。


示例查询:


  allDirectory(
    filter: 
      sourceInstanceName:  eq: "work" 
      relativeDirectory:  eq: "" 
    
  ) 
    edges 
      node 
        dir
        name
        extension
        relativeDirectory
        relativePath
      
    
  

查询所有类别。



  allDirectory(
    filter: 
      sourceInstanceName:  eq: "work" 
      relativeDirectory:  eq: "drawing" 
    
  ) 
    edges 
      node 
        dir
        name
        extension
        relativeDirectory
        relativePath
      
    
  

查询drawing类别的所有片段。



  allFile(
    filter: 
      sourceInstanceName:  eq: "work" 
      extension:  in: ["jpg", "jpeg", "png"] 
        relativeDirectory:  eq: "drawing/drawing-1" 
    
  ) 
    edges 
      node 
        dir
        name
        extension
        relativeDirectory
        relativePath
      
    
  

查询该作品drawing-1在类别drawing内的所有图片。


问题:

在最好的情况下,我想遍历每个类别并显示来自index.md 的带有图片和描述的工件。但是我怎样才能分别提取类别来查询碎片呢?我应该如何将这些实体与 Gatsby 映射在一起?我的概念是否具有误导性?如果你有什么好的建议,我应该考虑什么来实现我的目标,我会很高兴的。

编辑:

现在我正在摆弄sourceNodes() 并从文件夹结构中创建抽象节点。所需的 JSON 可能如下所示:


  "data": 
    "allWorkCategory": 
      "edges": [
        
          "node": 
            "path": "work/scuplture",
            "children": [
              
                "node": 
                  "internal": 
                    "type": "WorkItem",
                    "name": "Drawing 1",
                    "pictures": 
                       // ...
                    
                  
                
              
            ],
            "internal": 
              "type": "WorkCategory"
            
          
        ,
        
          "node": 
            "path": "work/drawing",
            "children": [],
            "internal": 
              "type": "WorkCategory"
            
          
        ,
        
          "node": 
            "path": "work/watercolor",
            "children": [],
            "internal": 
              "type": "WorkCategory"
            
          
        
      ]
    
  

【问题讨论】:

不确定您想要获得什么。您能否包含您尝试编写的查询的预期 json 结果? 我正在尝试将这些片段与其相应的父类别进行映射。当这些节点连接(子/父)时,就可以遍历整个树。 @CyrilDurand 我添加了一个示例,我认为解决方案可能与createParentChildLink 一起提供:gatsbyjs.org/docs/node-creation/… 【参考方案1】:

你可以使用createParentChildLink method创建gatsby节点之间的父/子关系,为了找到父节点你可以使用getNodesByType undocumented method。

const path = require('path')
exports.onCreateNode = (
    node,
    getNodesByType,
    actions
) => 
    const 
        createParentChildLink
     = actions

    if (node.internal.type === 'Directory') 
        if (node.sourceInstanceName === 'work') 
            // in some case the trailing slash is missing.
            // Always add it and normalize the path to remove duplication
            const parentDirectory = path.normalize(node.dir + '/')
            const parent = getNodesByType('Directory').find(
                n => path.normalize(n.absolutePath + '/') === parentDirectory
            )
            if (parent) 
                node.parent = parent.id
                createParentChildLink(
                    child: node,
                    parent: parent
                )
            
        
    

相应的查询可能如下所示:

    
      allDirectory(
        filter: 
          sourceInstanceName:  eq: "work" 
            relativeDirectory:  eq: "" 
        
      ) 
        edges 
          node 
            name
            relativePath
            children 
              __typename ... on Directory 
                name
                relativePath
              
            
          
        
      
    

输出如下:

    
      "data": 
        "allDirectory": 
          "edges": [
            
              "node": 
                "name": "drawing",
                "relativePath": "drawing",
                "children": [
                  
                    "__typename": "Directory",
                    "name": "drawing-1",
                    "relativePath": "drawing/drawing-1"
                  
                ]
              
            ,
            
              "node": 
                "name": "sculpture",
                "relativePath": "sculpture",
                "children": [
                  
                    "__typename": "Directory",
                    "name": "gaehnschreier",
                    "relativePath": "sculpture/gaehnschreier"
                  
                ]
              
            ,
            
              "node": 
                "name": "watercolor",
                "relativePath": "watercolor",
                "children": [
                  
                    "__typename": "Directory",
                    "name": "portrait-1",
                    "relativePath": "watercolor/portrait-1"
                  ,
                  
                    "__typename": "Directory",
                    "name": "portrait-2",
                    "relativePath": "watercolor/portrait-2"
                  
                ]
              
            
          ]
        
      
    

为了解释,__typename ... on Directory 让你有机会整体查询对应的节点。否则,您将仅获得子节点的 ID。为了更好地理解,请访问:https://graphql.org/learn/schema/#union-types

【讨论】:

好的,这很完美。但实际上我想查询完整的节点。那么,如何才能访问其余的数据呢?现在我只能访问idchildrenparent__typename

以上是关于使用 GatsbyJS 的 GraphQL 查询中的范围文件夹结构的主要内容,如果未能解决你的问题,请参考以下文章

在 GatsbyJS/GraphQL 中组合页面查询

GatsbyJS - 如何在 GraphQL 中查询长文本内容字段

如何使用 GatsbyJS 和 GraphQL 查询和显示包含多个图像的文件夹

GatsbyJS 网站的非页面组件中的 GraphQL 查询投诉

已解决 - GatsbyJS - GraphQL ACF 查询问题

并非所有 graphql 查询数据都在 GatsbyJS 页面上呈现