Need help with filtering data in Gatsby GraphiQL query
Tags: gatsby, graph
Published: 2020-05-01 22:10:40

Hi,

I"m trying to do something that seems trivial but it's completely beating me. Any help would be greatly appreciated!

I've created a basic Gatsby site with the default starter. I'm now trying to add some custom data (the people array) to gatsby-config.json like so:

    module.exports = {
      siteMetadata: {
        title: `Gatsby Default Starter`,
        description: `XXX`,
        author: `@gatsbyjs`,
        people : [
          { id : 1234, name : "Bill Smith", sales : 143, birthdate : "2233-03-22" },
          { id : 5678, name : "Roger Miller", sales : 281, birthdate : "2230-01-06" }
        ]
      },
      plugins: [
        `gatsby-plugin-react-helmet`,
        { resolve: `gatsby-source-filesystem`,
          options: { name: `images`, path: `${__dirname}/src/images`, }
        },
        `gatsby-transformer-sharp`,
        `gatsby-plugin-sharp`,
        { resolve: `gatsby-plugin-manifest`,
          options: {
            name: `gatsby-starter-default`, short_name: `starter`, start_url: `/`,
            background_color: `#663399`, theme_color: `#663399`, display: `minimal-ui`,
            icon: `src/images/gatsby-icon.png`
          }
        }
      ]
    }

Then, in GraphiQL, what I'm trying to do is a query to get a list of people, but limit it to just those with sales above 200, that's my end goal. So first, I did a basic test:

    {
      site {
        siteMetadata {
          people {
            name
          }
        }
      }
    }

That works, I get all people back. Then, I tried:

    {
      site {
        siteMetadata {
          people(sales: { gt: 200 }) {
            name
          }
        }
      }
    }

That gets me an error "Unknown argument sales on field people of type SiteSiteMetadata". That kinda seems to be telling me that Sift underneath Gatsby doesn't have any notion of my custom fields in its schema, or else that's the wrong syntax, either one would kind of make sense to me. So, as a test, I try this:

    {
      site {
        (author: { eq: "none" }) {
          author
          title
        }
      }
    }

My expectation is the query runs successfully but returns an empty result set since the author element's value isn't "none". But instead, I get the same basic error but now telling me "Unknown argument author on field siteMetadata of type Site" and now I'm confused because it seems like it should know about THOSE fields even if it doesn't know about arbitrary ones I add. Then again, maybe that query won't ever work because there's only a single siteMetaData object versus trying to query an array. I'm not sure.

So then I do some research and I see lots of references to 'filter', so I try this now:

    {
      site {
        siteMetadata(filter: { eq: "none" }) {
          author
          title
        }
      }
    }
    That gets me "Unknown argument filter on field siteMetadata of type Site."

I did find one post that seemed to possibly imply that you can't query custom data elements like this at all, but some replies seem to imply you, in fact, can (and clearly that first test worked, so the data is found, I just can't get the filtering to work). Maybe I'm using the wrong syntax, but if so then I can't seem to find what the correct syntax looks like (and what's worse is that in the Gatsby docs, the ONE example that MIGHT provide me an answer is error'ing out in the playground and I can't see the code).

I then tried putting the data in a separate file that get loaded with the gatsby-transformer-json plugin and tried to query that. The data gets loaded, but I still can't filter the query. I can do:

    {
      testData {
         {
          name
          sales
        }
      }
    }

...and that works, returns my data fine. But if I try:

    {
      testData {
        people(sales:{gt:200}) {
          name
          sales
        }
      }
    }

...or...

    {
      testData {
        people(filter:{sales:{gt:200}}) {
          name
          sales
        }
      }
    }

...I get the same types of errors. So, I think that at least proves this isn't an issue of querying it from siteMetaData specifically, but I still don't know how to make it do what I want.

For anyone who wants to reproduce this, just add the file data.json in the root of the project with this content:

    {
      "people" : [
        { "id" : 1234, "name" : "Bill Smith", "sales" : 143, "birthdate" : "2233-03-22" },
        { "id" : 5678, "name" : "Roger Miller", "sales" : 281, "birthdate" : "2230-01-06" }
      ]
    }

Then, add this to the plugins array in gatsby-config.json:

    {
      resolve: `gatsby-transformer-json`,
      options: { typeName: `testData` }
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: { name: `data`, path: `${__dirname}/data.json` }
    }

No other changes from the initially-generated project are needed. Then, just hop into GraphiQL and try to execute the queries above.

Or, to make things easier, I've created a codesandbox instance that demonstrates this:

[https://codesandbox.io/s/gatsby-graphql-querying-json-issue-47km4)

I also had the thought that maybe this is an issue with GraphiQL itself. So, I created a simple component:

    import React from "react"
    import { useStaticQuery, graphql } from "gatsby"
    
    const Test = () => {
    
    const testData = useStaticQuery(graphql`
      query TestDateQuery {
        testData(filter: {sales: {gte:200}}) {
          people {
            name
          }
        }
      }
    `)
    console.log("testData", testData);
    
      return (
        <div />
      )
    }
    
    export default Test;

I then dropped that into my main Layout component. I get the same sort of error (about filter being an unknown argument) rather than seeing my data. If I remove the filter, I DO see ALL the data. So, again, I can't figure out why just filter isn't working, but that's what I've narrowed it down to (and at this point it seems like that IS the correct syntax to use).

Thanks in advance!