Gatsby: Question: Comment faire une requête basée sur le nom du système de fichiers gatsby-source?

Créé le 27 juil. 2017  ·  20Commentaires  ·  Source: gatsbyjs/gatsby

J'ai plusieurs dossiers pour différents types de pages. C'est à dire. type1, type2, etc. qui contiennent des fichiers de démarque.

pages
   --type1
   --type2

Les fichiers de chaque dossier sont transformés en utilisant gatsby-transformer-remark .
Je souhaite interroger uniquement le contenu pour type1, type2, etc.
Par exemple, je veux une page de liste type1 qui contient une liste de toutes les pages 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',
      },
    },

Mon hypothèse était que vous pouviez interroger sur la base de la propriété name .

Quelque chose comme:

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

J'ai essayé toutes les requêtes différentes comme allSite et allFile mais je n'ai pas trouvé de solution.
J'ai aussi essayé

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

qui ne semble pas renvoyer quelque chose que je peux utiliser pour rendre le contenu:

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

Comment feriez-vous cela? Utilisez allFile et filtrez en fonction du nom du chemin (c'est-à-dire une regex qui correspond au dossier type1 et à l'extension markdown)?

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

Commentaire le plus utile

@ tsiq-swyx J'utilise quelque chose comme ça pour passer le champ collection de 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'),
    })

L'approche regex fonctionne, mais elle est fragile.

Tous les 20 commentaires

J'ai pensé que vous pouviez également filtrer le chemin en utilisant 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
          }
        }
      }
    }
}

Les nœuds de fichier ont le nom de l'instance source défini sur sourceInstanceName afin que vous puissiez l'utiliser pour les requêtes.

L'utilisation de regex est également une excellente solution que nous utilisons beaucoup sur gatsbyjs.org par exemple.

BTW, si vous ne l'utilisez pas déjà, GraphiQL est idéal pour explorer les données disponibles.

@KyleAMathews Existe-t-il un moyen d'utiliser sourceInstanceName dans la requête allMarkdownRemark ? J'espérais pouvoir obtenir le sourceInstanceName du nœud de fichier pour chaque nœud de démarque comme celui-ci, afin de pouvoir séparer mes articles de blog de mes projets sans utiliser de regex sur les chemins de fichier.

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

Mais le débogueur GraphQL montre que sourceInstanceName n'est pas disponible.

Comment recommandez-vous de filtrer les pages de démarque par type de source, comme les projets et les articles de blog? Ma solution actuelle pour cela est d'obtenir le fileAbsolutePath de chaque nœud de démarque:

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

Et puis pour tester s'il inclut certaines chaînes, comme /pages/blog/ ou /pages/projects/ . Mais cela sera interrompu si le chemin absolu vers le répertoire du site gatsby lui-même contient une de ces chaînes. Que recommandez-vous comme meilleure pratique dans ce cas? (Désolé si j'ai manqué quelque chose dans la documentation.)

@nwshane interroge simplement allFile et filtre-y. Vous pouvez filtrer les fichiers de démarque par internal.mediaType .

@KyleAMathews Comment combiner une requête sur allFile avec un tri sur frontmatter? Est-ce possible?

Essayer de trouver quelque chose de similaire.

Je peux filtrer par sous-dossier. Mais je ne vois pas frontmatter dans allFile .

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

METTRE À JOUR:

Cela a fonctionné pour moi.

J'ai des dossiers posts et pages dans le dossier content et mon gatsby-config.js pointe vers 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 Depuis ma dernière mise à jour j'ai plongé un peu plus dans le système de nœuds. Les nœuds allFile sont analysés par le gestionnaire de démarque, puis de nouveaux nœuds allMarkdownRemark sont créés. Donc, comme vous l'avez trouvé, il n'est pas possible de trier par frontmatter dans allFile car il n'est généré qu'une fois que l'analyseur de démarques entre en jeu. Le regex fonctionne, mais c'est un peu fragile à mon goût. Ma solution était de copier le nom de la collection (spécifié dans la configuration du plugin source du système de fichiers) du nœud de fichier dans le nœud de démarque via un hook onCreateNode . Je n'ai pas le code devant moi pour publier un exemple, mais c'était très rapide et j'ai ensuite un champ dans allMarkdownRemark lequel je peux filtrer.

Une autre possibilité comme @KyleAMathews l'a conseillé (dans mon cas, le nom de la source est projects )

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

@gbouteiller True, cela obtiendra le frontmatter et permettra de filtrer par sourceInstanceName . Le problème est que vous ne pouvez rien trier à l'intérieur de frontmatter utilisant cette approche. Il semble que les gens parlent d'articles de blog ici, et ils sont généralement triés par date. La date est généralement stockée dans le frontmatter .

Il n'y a aucun moyen de trier quelque chose de frontmatter et de filtrer par sourceInstanceName par défaut. Le sourceInstanceName n'est pas copié du nœud File dans le nœud markdownRemark . La seule option est d'utiliser une regex ou de copier des données selon mon article précédent.

Si le tri n'est pas nécessaire, ce qui peut être vrai dans de nombreux cas, alors votre approche a beaucoup de sens. Je n'avais pas réalisé que le childMarkdownRemark était disponible en tant que champ sur file , c'est super utile à savoir, merci pour le partage.

eu ce problème et a été un peu déçu que le champ "nom" ne fonctionne pas bien avec le markdownRemark. y a-t-il une petite victoire ici que nous pouvons faire pour transmettre ces informations?

EDIT: après avoir déconné un peu, j'ai réalisé que le champ id expose le chemin et vous pouvez filtrer en fonction de cela:

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
          }
        }
      }
    }
  }

le champ name du système de fichiers source ne fait toujours rien pour gatsby-transformer-remarque, je dirais qu'il améliore un peu le dx pour le faire passer comme un champ interrogeable / filtrable puisque gatsby-transformer-remark jamais existe sans gatsby-source-filesystem .

@ tsiq-swyx J'utilise quelque chose comme ça pour passer le champ collection de 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'),
    })

L'approche regex fonctionne, mais elle est fragile.

@chmac c'est très intelligent, et cela fonctionne, merci de partager votre solution. @KyleAMathews désolé de vous avoir tagué (lmk s'il y a quelqu'un d'autre à taguer) mais est-il possible que gatsby-source-filesystem fonctionne de cette façon (en passant sourceInstanceName à un champ de nœud ou à un autre champ) par défaut?

@ tsiq-swyx Je ne suis pas sûr à 100%, mais j'imagine que ce pourrait être une requête d'extraction assez simple! ;-)

Je pense que les responsables de gatsby ont des opinions bien arrêtées sur ces choses, donc je pense que cela vaut la peine d'en discuter avant d'envoyer des PR non sollicités au hasard :)

D'accord, je l'ai fait fonctionner, mais mon exportation createPages n'utilise qu'un seul modèle

Il est intéressant de voir que l'utilisation de gatsby-source-filesystem ne nécessite pas du tout AllFile dans graphql. Ce qui peut prêter à confusion et cela ne se reflète pas dans la documentation.
j'utilise
const { createPage } = actions const result = await graphql(` query { allMarkdownRemark { edges { node { fields { slug } frontmatter { lang } } } } } `)
et il crée des pages sans problème. Je ne sais pas cependant si le même principe s'applique à gatsby-source-git

Merci @chmac

Je dois créer des pages basées sur le nom gatsby-source-filesystem ...

alors voici ma solution:

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}`
    })
  }
}

C'est intéressant, jamais trouvé une telle option node.parent existe

Le lundi 27 avril 2020, Noman Gul [email protected] a écrit:

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

Je dois créer des pages basées sur le nom du système de fichiers gatsby-source ...

alors voici ma solution:

const {createFilePath} = require ("gatsby-source-filesystem")
exports.onCreateNode = ({nœud, actions, getNode}) => {
const {createNodeField} = actions

if (node.internal.type === Mdx && getNode (node.parent) .sourceInstanceName === "carrières") {
valeur const = createFilePath ({nœud, getNode})

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

}
}

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/gatsbyjs/gatsby/issues/1634#issuecomment-619670883 ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AAEQPFX6KR7NUIY33Q7V4MDROTS7PANCNFSM4DUUPK6A
.

Je suis dans la même situation qui je pense est un cas assez courant et après avoir lu ce fil; La meilleure solution et non-piratée, à mon avis, est:

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

Mon type de contenu projects est en /content/projects/ .

Cette page vous a été utile?
0 / 5 - 0 notes