简体   繁体   English

Gatsby的GraphQL查询 - 使用灵活的内容模型进行内容设置

[英]GraphQL queries for Gatsby - Contentful setup with a flexible content model

I have a gatsby site with the contentful plugin and graphql queries (setup is working). 我有一个gatsby网站, 内容 丰富的 插件graphql查询 (设置正常)。

[EDIT] My gatsby setup pulls data dynamically using the pageCreate feature. [编辑]我的gatsby设置使用pageCreate功能动态提取数据。 And populates my template component, the root graphql query of which I've shared below. 并填充我的模板组件,我在下面分享的根graphql查询。 I can create multiple pages using the setup if the pages on contentful follow the structure given in the below query. 如果内容上的页面遵循以下查询中给出的结构,我可以使用设置创建多个页面。 [/EDIT] [/编辑]

My question is about a limitation I seemed to have come across or just don't know enough grpahql to understand this yet. 我的问题是关于我似乎遇到的限制,或者只是不知道足够的grpahql来理解这一点。

My high level content model 'BasicPageLayout' consists of references to other content types through the field 'Section'. 我的高级内容模型'BasicPageLayout'包含通过字段'Section'对其他内容类型的引用。 So, it's flexible in terms of which content types are contained in the 'BasicPageLayout' and the order in which they are added. 因此,它在'BasicPageLayout'中包含哪些内容类型以及添加它们的顺序方面具有灵活性。

Root page query 根页面查询

export const pageQuery = graphql`
query basicPageQuery {
contentfulBasicPageLayout(pageName: {eq: "Home"}) {

    heroSection {
        parent {
            id
        }
        ...HeroFields
    }

    section1 {
        parent {
            id
        }
        ...ContentText

    }

    section2 {
        parent {
            id
        }
        ...ContentTextOverMedia
    }

    section3 {
        parent {
            id
        }
        ...ContentTextAndImage
    }

    section4 {
        parent {
            id
        }
        ...ContentText
    }
  }
}

The content type fragments all live in the respecitve UI components. 内容类型片段都存在于相应的UI组件中。 The above query and setup are working. 上面的查询和设置正在运行。

Now, I have "Home" Hard coded because I'm having trouble creating a flexible reusable query. 现在,我有“Home”硬编码,因为我在创建灵活的可重用查询时遇到了麻烦。 I'm taking advantage of contentful's flexible nature when creating the models, but haven't found a way to create that flexibility in the graphql query for it. 我在创建模型时充分利用了内容的灵活性,但还没有找到一种方法来为它创建graphql查询的灵活性。

What I do know: Graphql query is resolved at run time, so everything that needs to be fetched should be in that query. 我所知道的: Graphql查询在运行时被解析,因此需要获取的所有内容都应该在该查询中。 It can't be 'dynamic'. 它不能是“动态的”。

Issue: The 'Section' fields in the basicPageLayout can link to any content type. 问题: basicPageLayout中的“Section”字段可以链接到任何内容类型。 So we can mix and match the granular level content types. 因此,我们可以混合和匹配粒度级别的内容类型。 How do I add the content type fragment (like ContentTextAndImage vs ContentText) so it is appropriate for that section instance ('Section' field in the query)? 如何添加内容类型片段(如ContentTextAndImage vs ContentText),以便它适用于该部分实例(查询中的“部分”字段)?

In other words I'd like the root query to get 'Home' data which might have 4 sections, all of type - ContentTextOverMedia as well as 'About ' data that might have also have 4 sections but with alternating types - ContentText and ContentTextAndImage 换句话说,我希望根查询获得“Home”数据,这些数据可能包含4个部分,所有类型 - ContentTextOverMedia以及“About”数据,这些数据可能还有4个部分但具有交替类型 - ContentText和ContentTextAndImage

This is the goal because I want to create content (Pages) by mix-matching content types on contentful, without needing to update the code each time a new Page is created. 这是我的目标,因为我想通过在内容上混合匹配内容类型来创建内容(Pages),而无需在每次创建新页面时更新代码。 Which is why Contentful is useful and was picked in the first place. 这就是为什么Contentful很有用并且首先被选中的原因。

My ideas so far: 我的想法到目前为止:

A. Run two queries, in series. A.串联运行两个查询。 One fetches the parent.id on each section and that holds the content type info. 一个获取每个部分的parent.id并保存内容类型信息。 Second fetches the data using the appropriate fragment. 第二次使用适当的片段获取数据。

B. Fetch the JSON file of the basicPageLayouts content instance (such as 'Home') separately through Contentful API, and using that JSON file create the graphql string to be used in each instance (So, different layout for Home, About, and so on) This needs more experimentation, not sure if it's viable, could also be more complex then it needs to be. B.通过Contentful API分别获取basicPageLayouts内容实例的JSON文件(例如'Home'),并使用该JSON文件创建要在每个实例中使用的graphql字符串(因此,Home,About等的不同布局这需要更多的实验,不确定它是否可行,也可能比它需要的更复杂。

So, please share thoughts on the above paths that I'm exploring or another solution that I haven't considered using graphql or gatsby's features. 所以,请分享我正在探索的上述路径的想法或我没有考虑使用graphql或gatsby功能的其他解决方案。

This is my first question on SO btw, I've spent some time on refining it and trying to follow the guidelines but please do give me feedback in comments so I can improve even if you don't have an answer to my question. 这是我关于SO btw的第一个问题,我花了一些时间来完善它并试图遵循指南,但请在评论中给我反馈,这样即使你没有我的问题的答案,我也可以改进。 Thanks in advance. 提前致谢。

If I understood correctly you want to create pages dynamically from the data coming from Contentful. 如果我理解正确,您希望根据来自Contentful的数据动态创建页面。

You can achieve this using the Gatsbyjs Node API specifically createPage . 您可以使用Gatsbyjs Node API专门创建createPage来实现此目的。

In your gatsby-node.js file you can have something like this 在你的gatsby-node.js文件中你可以有这样的东西

const fs = require('fs-extra')
const path = require('path')

exports.createPages = ({graphql, boundActionCreators}) => {
  const {createPage} = boundActionCreators
  return new Promise((resolve, reject) => {
    const landingPageTemplate = path.resolve('src/templates/landing-page.js')
    resolve(
      graphql(`
        {
          allContentfulBesicPageLayout {
            edges {
              node {
                pageName
              }
            }
          }
        }
      `).then((result) => {
        if (result.errors) {
          reject(result.errors)
        }
        result.data.allContentfulBesicPageLayout.edges.forEach((edge) => {
          createPage ({
            path: `${edge.node.pageName}`,
            component: landingPageTemplate,
            context: {
              slug: edge.node.pageName // this will passed to each page gatsby create
            }
          })
        })
        return
      })
    )
  })
}

Now in your src/templates/landing-page.js 现在在你的src/templates/landing-page.js

import React, { Component } from 'react'
const LandingPage = ({data}) => {
    return (<div>Add you html here</div>)

}
export const pageQuery = graphql`
query basicPageQuery($pageName: String!) {
contentfulBasicPageLayout(pageName: {eq:  $pageName}) {

    heroSection {
        parent {
            id
        }
        ...HeroFields
    }

    section1 {
        parent {
            id
        }
        ...ContentText

    }

    section2 {
        parent {
            id
        }
        ...ContentTextOverMedia
    }

    section3 {
        parent {
            id
        }
        ...ContentTextAndImage
    }

    section4 {
        parent {
            id
        }
        ...ContentText
    }
  }
}

note the $pageName param that's what was passed to the component context when creating a page. 请注意$pageName参数,它是在创建页面时传递给组件上下文的内容。 This way you will end up creating as many pages as you want. 这样,您最终将创建任意数量的页面。 Please note: the react part of the code was not tested but I hope you get the idea. 请注意:代码的反应部分没有经过测试,但我希望你能得到这个想法。

Update : To have a flexible query you instead of having your content Types as single ref field, you can have one field called sections and you can add the section you want there in the order you desire. 更新 :要获得灵活的查询,而不是将内容类型作为单个引用字段,您可以使用一个名为sections的字段,并且可以按所需顺序添加所需的部分。 Your query will look like this 您的查询将如下所示

    export const pageQuery = graphql`
    query basicPageQuery($pageName: String!) {
    contentfulBasicPageLayout(pageName: {eq:  $pageName}) {
       sections {
         ... on ContentfulHeroFields {
           internal {
              type
        }
    }
}         

} }

Khaled 哈立德

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM