4

I started using Gatsby along with GraphQL to return a query that lists all galleries that are part of a specific category. In this example the category is called "Lifestyle". This all works successfully and I get an array with all of the Galleries in the category. I also need to sort this array based off a sub field called "date". Is that possible to do via the GraphQL query itself? I tried adding (sort: { fields: [date], order: DESC }) to the gallery field but that didn't work.

Any thoughts on how to achieve this or is this as close as GraphQL can get me to what I need?

Thanks in advance for any help. Still trying to wrap my head around GraphQL.

Ryan

Example of my current query

Ryan Wiemer
  • 41
  • 1
  • 2

2 Answers2

3

Could you provide a bit more details about your content model?

  • If you use a "Reference" field in contentful, it is sadly not possible as of now with the plugin as far as I know.
  • If you use a "Short text, list" field, like the tags in the default example.

With the default example, you can do the following query:

    {
          allContentfulPost(filter:{tags:{eq:"fantasy"}}, sort:{fields:[date], order:DESC}) {
            edges {
              node {
                title {
                  childMarkdownRemark {
                    html
              }
            }
            slug
            date
          }
        }
      }
    }

It will give you the following result:

    {
      "data": {
        "allContentfulPost": {
          "edges": [
            {
              "node": {
                "title": {
                  "childMarkdownRemark": {
                    "html": "<p>Disney Movie</p>"
                  }
                },
                "slug": "down-the-rabbit-hole",
                "date": "2017-11-26"
              }
            },
            {
              "node": {
                "title": {
                  "childMarkdownRemark": {
                    "html": "<p>Old book</p>"
                  }
                },
                "slug": "down-the-rabbit-hole-2",
                "date": "1865-11-26"
              }
            }
          ]
        }
      }
    }
  • Awww okay. Yes, my current content model had two types: Gallery and Category. I was using a reference field within the Gallery content type to associate it with a given category. Since it is still very early on in this project I can switch to using a regular text field per your example and give that a shot. Seems like a reference field would have been the "correct" method for this but if it is a limitation of the `gatsby-source-contentful` plugin that is fine. As long as I get the data I need in the correct order I will be happy. – Ryan Wiemer Nov 02 '17 at 13:18
  • 1
    Realise you've probably solved this already, but you might also consider sorting in javascript after getting the data from GraphQL. It won't always be the right approach, but might be useful in some scenarios. Lodash / underscore have `_.sortBy()` functions that make it pretty easy. – chmac Feb 14 '18 at 16:32
1

I came across this same issue as I was trying to sort posts from a category tag that I was using in Contentful. Like @chmac said, you can sort the data from GraphQL with Javascript.

I had to search for a good example, but I finally found one in this Gatsby starter:

Github: https://github.com/ryanwiemer/gatsby-starter-gcn/blob/master/src/templates/tag.js

Live Example: https://gcn.netlify.com/tag/fancy/

You can see in the source file that they sorted the data in a new constant called posts using moment (https://www.npmjs.com/package/moment) and lodash. In my personal example I had to tweak my constant like so:

const courses = orderBy(
            this.props.data.contentfulCategory.course,
            // eslint-disable-next-line
            [object => new moment(object.createdAt)],
            ['desc']
          )

Then I just used a map function like so in the component return:

{/* Courses */}
{courses.map(course => (
    <div className="hero__profile" key={course.id}>
        <h2>{course.title}</h2>
    </div>
))}

I hope this helps!