Gatsby: Pregunta: ¿Cómo puedo realizar una consulta basada en el nombre del sistema de archivos fuente gatsby?

Creado en 27 jul. 2017  ·  20Comentarios  ·  Fuente: gatsbyjs/gatsby

Tengo varias carpetas para diferentes tipos de páginas. Es decir. type1, type2, etc., que contienen archivos de rebajas.

pages
   --type1
   --type2

Los archivos de cada carpeta se transforman usando gatsby-transformer-remark .
Quiero consultar solo contenido para type1, type2, etc.
Por ejemplo, quiero una página de lista de tipo1 que contenga una lista de todas las páginas de tipo1.

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

Mi suposición era que podría realizar consultas basadas en la propiedad name .

Algo como:

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

Intenté todas las consultas diferentes como allSite y allFile pero no pude encontrar una solución.
También lo intenté

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

que no parece devolver algo que pueda usar para renderizar contenido:

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

¿Como lo harias? ¿Usar allFile y filtrar según el nombre de la ruta (es decir, una expresión regular que coincida con la carpeta type1 y la extensión de descuento)?

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

Comentario más útil

@ tsiq-swyx Estoy usando algo como esto para pasar el campo collection de File a 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'),
    })

El enfoque regex funciona, pero es frágil.

Todos 20 comentarios

Pensé que también podrías filtrar la ruta usando 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
          }
        }
      }
    }
}

Los nodos de archivo tienen el nombre de la instancia de origen establecido como sourceInstanceName por lo que puede usarlo para consultas.

Usar expresiones regulares también es una gran solución que usamos mucho en gatsbyjs.org, por ejemplo.

Por cierto, si aún no lo está utilizando, GraphiQL es excelente para explorar qué datos están disponibles.

@KyleAMathews ¿Hay alguna forma de usar sourceInstanceName en la consulta allMarkdownRemark ? Esperaba poder obtener el sourceInstanceName del nodo de archivo para cada nodo de rebajas como este, para poder separar las publicaciones de mi blog de mis proyectos sin usar expresiones regulares en las rutas del archivo.

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

Pero el depurador GraphQL muestra que sourceInstanceName no está disponible.

¿Cómo recomiendas filtrar las páginas de rebajas por tipo de fuente, como proyectos y publicaciones de blog? Mi solución actual para esto es obtener el fileAbsolutePath de cada nodo de rebajas:

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

Y luego para probar si incluye ciertas cadenas, como /pages/blog/ o /pages/projects/ . Pero esto se romperá si la ruta absoluta al directorio del sitio gatsby contiene una de estas cadenas. ¿Qué recomienda como mejor práctica en este caso? (Lo siento si me perdí algo en la documentación).

@nwshane solo consulta allFile y filtra allí. Puede filtrar los archivos de rebajas por internal.mediaType .

@KyleAMathews ¿Cómo se combina una consulta en allFile con una ordenación en frontmatter? ¿Es eso posible?

Tratando de averiguar algo similar.

Puedo filtrar por subcarpeta. Pero no puedo ver frontmatter en allFile .

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

ACTUALIZAR:

Esto funcionó para mí.

Tengo carpetas posts y pages dentro de la carpeta content y mi gatsby-config.js apunta a 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 Desde mi última actualización, me allFile son analizados por el controlador de rebajas y luego se crean nuevos nodos allMarkdownRemark . Entonces, como descubrió, no es posible ordenar por frontmatter en allFile porque solo se genera una vez que se activa el analizador de rebajas. La expresión regular funciona, pero es un poco frágil para mi gusto. Mi solución fue copiar el nombre de la colección (especificado en la configuración del complemento de origen del sistema de archivos) desde el nodo del archivo al nodo de rebajas a través de un gancho onCreateNode . No tengo el código delante para publicar un ejemplo, pero fue muy rápido y luego tengo un campo dentro de allMarkdownRemark que puedo filtrar.

Otra posibilidad como aconsejó @KyleAMathews (en mi caso, el nombre de la fuente es projects )

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

@gbouteiller Cierto, obtendrá el frontmatter y permitirá filtrar por sourceInstanceName . El problema es que no puede ordenar por nada dentro de frontmatter usando este enfoque. Parece que la gente está hablando de publicaciones de blog aquí, y generalmente están ordenadas por fecha. La fecha normalmente se almacena dentro de frontmatter .

No hay forma de ordenar por algo de frontmatter y filtrar por sourceInstanceName de forma predeterminada. El sourceInstanceName no se copia del nodo File en el nodo markdownRemark . La única opción es usar una expresión regular o copiar algunos datos según mi publicación anterior.

Si no se requiere la clasificación, lo que puede ser cierto en muchos casos, entonces su enfoque tiene mucho sentido. No me había dado cuenta de que childMarkdownRemark estaba disponible como un campo en file , es muy útil saberlo, gracias por compartir.

tuvo este problema y me decepcionó un poco que el campo "nombre" no funcione bien con el markdownRemark. ¿Hay alguna pequeña victoria aquí que podamos hacer para transmitir esta información?

EDITAR: después de jugar un poco, me di cuenta de que el campo de identificación expone la ruta y puede filtrar en función de eso:

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

el campo name del sistema de archivos fuente todavía no hace nada para gatsby-transformer-comment, yo diría que mejora un poco el dx para que fluya como un campo consultable / filtrable ya que gatsby-transformer-remark nunca existe sin gatsby-source-filesystem .

@ tsiq-swyx Estoy usando algo como esto para pasar el campo collection de File a 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'),
    })

El enfoque regex funciona, pero es frágil.

@chmac esto es muy inteligente y funciona, gracias por compartir su solución. @KyleAMathews lo siento por etiquetarte (lmk si hay alguien más para etiquetar) pero ¿es posible que gatsby-source-filesystem funcione de esta manera (pasando sourceInstanceName a un campo de nodo o algún otro campo) por defecto?

@ tsiq-swyx No estoy 100% seguro, ¡pero me imagino que podría ser una solicitud de extracción bastante simple! ;-)

Creo que los mantenedores de Gatsby tienen opiniones sólidas sobre estas cosas, así que creo que vale la pena discutirlo antes de enviar PR no solicitadas al azar :)

De acuerdo, lo hice funcionar, pero mi exportación de createPages solo usa una plantilla

Es interesante ver que usar gatsby-source-filesystem no requiere AllFile en graphql en absoluto. Lo que puede generar confusión y no se refleja en la documentación.
estoy usando
const { createPage } = actions const result = await graphql(` query { allMarkdownRemark { edges { node { fields { slug } frontmatter { lang } } } } } `)
y crea páginas sin problemas. Sin embargo, no estoy seguro si se aplica el mismo principio a gatsby-source-git

Gracias @chmac

Tengo que crear páginas basadas en el gatsby-source-filesystem name ...

así que aquí está mi solución:

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

Esto es interesante, nunca encontré tal opción node.parent existe

El lunes 27 de abril de 2020, Noman Gul [email protected] escribió:

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

Tengo que crear páginas basadas en el nombre de gatsby-source-filesystem ...

así que aquí está mi solución:

const {createFilePath} = require ("gatsby-source-filesystem")
export.onCreateNode = ({nodo, acciones, getNode}) => {
const {createNodeField} = acciones

if (node.internal.type === Mdx && getNode (node.parent) .sourceInstanceName === "carreras") {
valor constante = createFilePath ({nodo, getNode})

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

}
}

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/gatsbyjs/gatsby/issues/1634#issuecomment-619670883 ,
o darse de baja
https://github.com/notifications/unsubscribe-auth/AAEQPFX6KR7NUIY33Q7V4MDROTS7PANCNFSM4DUUPK6A
.

Estoy en la misma situación que creo que es un caso bastante común y después de leer este hilo; La mejor solución y no pirata, en mi opinión, es:

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

Mi tipo de contenido projects está en /content/projects/ .

¿Fue útil esta página
0 / 5 - 0 calificaciones