10

I'm working on a news site which will have articles, each with one or multiple respective authors. If you click on an author's name, it will take you to a page displaying their information and a list of articles they have contributed to.

So each article has an authors property, which in turn is an array of author objects with properties: full name, slug (lowercase version of full name with spaces replaced by dashes), etc.

Is it possible to filter the articles by a particular author's slug when defining the query?

query authorQuery($slug: String!) {
  allContentfulArticle(filter: { //not sure what to do here }) {
    edges {
      node {
        title
        slug
        authors {
          name
          slug
        }
      }
    }
  }
}

My other option would be to load all of the articles, then setup a filter in the component like so:

const articles = data.allContentfulArticle.edges.filter(({ node }) => {
  return node.authors.some((author) => author.slug === data.contentfulAuthor.slug);
});

This wouldn't be the end of the world, however it goes against the GraphQL principle of only loading the data you need.

dougmacklin
  • 2,290
  • 9
  • 37
  • 66

1 Answers1

8

What you want to achieve here if I understood correctly, you want to group articles by author. You can achieve that if you query and apply filter to allContentfulAuthor and request the article field, like so:

{
  allContentfulAuthor(filter: {slug: {eq: "myslug"}}) {
    edges {
      node {
        name
        article {
          title
          slug
        }
      }
    }
  }
}

Note that the article name is your contentTypeId for your articles.

Khaled Garbaya
  • 1,401
  • 17
  • 20
  • 1
    Would this work if Author did not have an article field? – Luke Flournoy Jan 31 '18 at 17:35
  • 1
    Thanks Khaled! I did not realize that the author object would automatically contain an article field since I defined the relationship as articles containing authors, and not vice-versa. What is responsible for that magic, Contentful itself? Very cool. To answer your question @LukeFlournoy, the answer seems to be yes :) – dougmacklin Jan 31 '18 at 21:56
  • That’s called back reference from the author to the article, that has nothing todo with Contentful it’s more GraphQl magic – Khaled Garbaya Jan 31 '18 at 21:58
  • Thanks again, loving graphql more and more each day. One quick followup question for you related to nesting: would it be possible to sort the articles by a field here as well? meaning in your example above put `article(sort:{fields:[date], order:DESC}) { title slug }`. – dougmacklin Jan 31 '18 at 22:03
  • It could work, you can test that on localhost:8000/___graphql , Gatsbyjs spawn a grapgiql server for you when in develop mode, that’s your best friend – Khaled Garbaya Jan 31 '18 at 22:06
  • yeah when I try to do that I get an error: `Unknown argument \"sort\" on field \"article\" of type \"ContentfulAuthor\"."`. Meanwhile this same sort method works fine when querying articles directly, rather than querying them as a property of authors. wondering if it's an issue that has to do with the reference you alluded to earlier – dougmacklin Jan 31 '18 at 22:09
  • Unfortunately, that is not possible – Khaled Garbaya Jan 31 '18 at 23:13
  • Gotcha, I will sort within the component definition. Thanks for all the help @KhaledGarbaya! – dougmacklin Jan 31 '18 at 23:33
  • Is there a way to make the `"myslug"` in your example dynamic? – Robin Métral Jan 21 '19 at 15:10
  • Yes , through `allContentfulAuthor(filter: {slug: {eq: $slug}}) {` where $slug is passed through the context object when creating this page in the gatsby-node.js – Khaled Garbaya Jan 21 '19 at 15:12