Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
207 views
in Technique[技术] by (71.8m points)

node.js - Combing related data from two different sources in a single Gatsby page

I'm creating a blog where each blog page will show a map using leaflet with a GPX route on it. Below the map will be some statistics and some text and images.

I have the text and images part defined in mark down so i figured the way to handle this would be to define my gpx filename in the frontmatter like so:

---
title: Awesome Blog Post Title
author: Cancrizan
date: 2021-01-04
gpxFile: activity4835702422
---
BLOG POST here

where the field gpxFile refers to a a file in my project src/gpx/activity4835702422.gpx.

I've written a transformer plugin that will read in the GPX file so that it can be queried like this:

query MyQuery {
  allActivity4835702422Gpx {
    edges {
      node {
        geometry {
          coordinates
        }
      }
    }
  }
}

and outputs something like this:

{
  "data": {
    "allActivity4835702422Gpx": {
      "edges": [
        {
          "node": {
            "geometry": {
              "coordinates": [
                [
                  -1.2134187016636133,
                  52.92038678191602,
                  29.399999618530273
                ],
                [
                  -1.2134256586432457,
                  52.92039977386594,
                  29.399999618530273
                ],
                ...,
              ]
            }
          }
        }
      ]
    }
  },
  "extensions": {}
}

I want to access that node based on the frontmatter of the markdown file and i'm not sure how?

Can anyone suggest a solution or am i going about this the wrong way?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The structure and the mindset you've followed is perfectly valid, the only part you're missing is to pass the gpxFile to your template in order to create another query based on that parameter.

Your gatsby-node.js should look like something like this:

const path = require("path")

exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions

  const result = await graphql(
    `
      {
        allMarkdownRemark(limit: 1000) {
          edges {
            node {
              frontmatter {
                title
                author
                date
                gpxFile
                slug
              }
            }
          }
        }
      }
    `
  )

  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

  const postTemplate= path.resolve(`src/templates/post.js`);

  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    const path = node.frontmatter.path
    createPage({
       path: `/posts/${node.frontmatter.slug}`,
       component: postTemplate,
       context: {
         gpxFile: node.frontmatter.gpxFile,
         path: node.frontmatter.slug
       }
    })
  })
}

The idea is to use context API to pass data (gpxFileData and path) to your template (postTemplate) to use it as a filter for your markdown files.

In your postTemplate, your query should look like:

export const postData = graphql`
    query getArticleData($path: String!, $gpxFile: String) {
        post: markdownRemark (fields: {frontmatter: { slug: { eq: $path }}}) {
            html
            excerpt (pruneLength: 350)
            frontmatter {
              title
              author
              date
              gpxFile
              slug
            }
        }
        gpxFileData: allFile(relativePath: { in: $gpxFile })
           # your gpx data here
        }
    }
`;

It's quite self-explanatory, basically, you are passing via context the necessary data to make a query in your template (gpxFileData) from your gatsby-node.js. There, you can create a new query, allFile, filtering by relativePath (you may need to access to file directly or use absolutePath, test it in localhost:8000/___graphql) and retrieve the whole data using props.data.post and post.data.gpxFileData.

Disclaimer: I'm assuming that you've set your filesystem (gatsby-source-filesystem) properly to use allFile across your .gpx files.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...