Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

markdown - Gatsby & Graphql: Filter allMarkdownRemark for pages matching a variable

I'm trying to filter all my markdown pages, for pages which match a certain category(specified in markdown frontmatter) and pages which are not the pages being currently visited. All pages created from markdown though are receiving the same result for allMarkdownRemark though and are not filtering any results.

I would like to know how to get all the pages to not have the same result for allMarkdownRemark, and would like the results in allMarkdownRemark to be filtered

My page query looks something like

    export const pageQuery = graphql`
        query ArticleQuery($path: String, $category: String, $title: String) {
            allMarkdownRemark(
                filter: {
                    frontmatter: {
                        category: {eq: $category},
                        title: {ne: $title}
                    }
                },
                sort: {
                    order: DESC, fields: [frontmatter___date] 
                }
            ) {
            ...

And my gatsby-node.js looks like

const { createFilePath } = require(`gatsby-source-filesystem`);
const { fmImagesToRelative } = require('gatsby-remark-relative-images-v2');
const path = require("path");

exports.createPages = async ({ actions: { createPage }, graphql }) => {
    const postTemplate = path.resolve(`src/components/ArticlePage.jsx`);

    const result = await graphql(`
    {
      allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___title] }
      ) {
        edges {
          node {
            fields {
              slug
            }
            frontmatter {
              category
              title
            }
          }
        }
      }
    }
  `);

    if (result.errors) {
        return Promise.reject(result.errors);
    };

    result.data.allMarkdownRemark.edges.forEach(({ node }) => {
        createPage({
            path: `${node.fields.slug}`,
            category: `${node.frontmatter.category}`,
            title: `${node.frontmatter.title}`,
            component: postTemplate,
            context: {node}
        });
    });
};

exports.onCreateNode = ({ node, getNode, actions }) => {
  fmImagesToRelative(node);
  if (node.internal.type === `MarkdownRemark`){
    actions.createNodeField({
        node,
        name: `slug`,
        value: createFilePath({ node, getNode, basePath: `pages`, trailingSlash: true }),
    });
  }
};

All markdown files include something like this in them

---
title: "My title"
category: "My category"
---

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

1 Reply

0 votes
by (71.8m points)

I would like to know how to get all the pages to not have the same result for allMarkdownRemark, and would like the results in allMarkdownRemark to be filtered

In these cases, what is commonly used is a key field for all kind of markdown files that you want to group. As you said, allMarkdownRemark is a schema inferred by Gatsby (and their transformers and sharps) at the time that you allow it to access to your filesystem so you can't distinguish directly the type of markdown. This is the simplest, cleanest, and less invasive option. You just need to:

---
title: "My title"
category: "My category"
key: "pageTypeOne"
---

Then, in your queries, you just need to filter for key field when needed:

export const pageQuery = graphql`
    query ArticleQuery($path: String, $category: String, $title: String) {
        allMarkdownRemark(
            filter: {
                frontmatter: {
                    category: {eq: $category},
                    title: {ne: $title}
                    key: {eq: "pageTypeOne" }
                }
            },
            sort: {
                order: DESC, fields: [frontmatter___date] 
            }
        ) {
        ...

You can change the string-based approach to a context one if needed in your createPage API in your gatsby-node.js. Or, depending on your needs, create a filtered query in your gatsby-node.js, creating different queries for each page, in that way your markdownRemark will be filtered already.

Alternatively, you can add different filesystems (gatsby-source-filesystem) and use the inferred sourceInstanceName to get your data:

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

Then:

{
  allFile(filter: { sourceInstanceName: { eq: "posts" } }) {
    edges {
      node {
        extension
        dir
        modifiedTime
      }
    }
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...