Gatsby: [feature] Add support for arguments on GraphQL fields that return arrays

Created on 21 Jan 2018  Â·  17Comments  Â·  Source: gatsbyjs/gatsby

Description

It would be nice to have the ability to assign arguments onto dynamically-created schemas' node fields that return arrays.

Arguments could be near-identicle to *Connection types:

  • skip
  • limit
  • sort
  • filter

Those existing arguments could be modified to support array-specific needs, like exposure of an __index-type field and array index wrapping:

characters(sort: { fields: [__index], order: ASC }, limit: 2)

New arguments could also be created to simplify filtering arrays and/or return specific indicies:

  • in: identicle to how this is used in the *Connection argument filter, except it is applied directly onto the array-returning field (e.g. characters(in: {name: {eq: "Frodo Baggins"}}))
  • index: allow retrieval of specific indices by passing them to index in an array (e.g. characters(index: [0, 1]), characters(index: [2]), characters(index: [-1]))

@KyleAMathews suggested I open an issue to add this support for passing arguments to sub-arrays on the Discord chat; the only issues that I found that pertained to this issue are #2430 and #1645.

Environment

Gatsby version: ^1.9.158
Node.js version: 8.9.1
Operating System: MacOS El Capitan 10.11.6

Steps to reproduce

I have set up a working demo project that features some sample data, some working queries, and an example of the aforementioned experimental array field arguments.

help wanted

All 17 comments

maybe related to #3190

@flmuel no these are unrelated — @geoffdavis92 is asking for the ability to sort/filter on graphql lists not linked nodes.

I think I'm running into this issue right now with gatsby-transformer-json. Any array data in my json is being transformed into an InputObject and available in Graph via in: []? Anytime I include this in in my query/filter I am getting null data returned.

In my json, I have an array of objects, I would expect my query to be this, or similar:

{
    dataJson(data: { pages: { name: { eq: "index" } }) {
        data {
          pages {
            name
          }
       }
    }
}

Because of that in, graph "suggests" this query:

{
    dataJson(data: { pages: { in: { name: { eq: "index" } } }) {
        data {
          pages {
            name
          }
       }
    }
}

But anytime in is included at all, data just returns null.. I'm guessing this is related to this issue, but I'm curious if I'm just writing my query wrong.

@pieh might have an answer for @loremipson's question above?

It seems gatsby doesn't actually support properly constructing input schema for array of objects (I don't think we should have that eq inside in operator). Will check if we can fix it.

@pieh I'd need that feature for my Prismic source to grab the tags.

I get as an output:

"tags": [
                {
                  "tag": {
                    "document": [
                      {
                        "data": {
                          "tag": "elitepvpers"
                        }
                      }
                    ]
                  }
                },
                {
                  "tag": {
                    "document": [
                      {
                        "data": {
                          "tag": "Wallpaper"
                        }
                      }
                    ]
                  }
                }
              ],

@LeKoArts a good start to fixing this would be to create a PR with a new test for this functionality in https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js

That test should be failing and then it'd be easy for one of us to figure out how to fix it.

@KyleAMathews @LeKoArts I think that the error happens when filtering on an array of objects. I think this kind of data structure is needed in order to re-create the error.

Feature got merged in the meantime.

Thanks all! Great to see @KyleAMathews @LekoArts

Hey @LekoArts or @KyleAMathews I can't work out from the docs or code how this is meant to work if it has been merged. I get into a circular loop of duplicate issues.

I have this query

{
  dataJson(data: {allRestaurants: {elemMatch: {id: {eq: "132"}}}}) {
    data {
      allRestaurants {
        id
        title
      }
    }
  }
}

but it doesn't do any filtering. e.g. results

{
  "data": {
    "dataJson": {
      "data": {
        "allRestaurants": [
          {
            "id": "132",
            "title": "Jervois Steak House"
          },
          {
            "id": "682",
            "title": "Bessie"
          },
          {
            "id": "71",
            "title": "Blue Kanu"
          },
          {
            "id": "1050",
            "title": "Bazaar Interactive Marketplace"
          },
          {
            "id": "1300",
            "title": "Louis Champagne & Oyster Bar"
          },
          {
            "id": "2018",
            "title": "Takumi Japanese Restaurant & Bar"
          },
          {
            "id": "1343",
            "title": "Euro Bar & Restaurant"
          },
          {
            "id": "2360",
            "title": "Orleans Auckland"
          },
          {
            "id": "1053",
            "title": "The Grille by Eichardt's"
          },
          {
            "id": "2350",
            "title": "Orleans"
          },
          {
            "id": "2245",
            "title": "Vault 21"
          },.......

Any idea what I am doing wrong or is this not possible? My GraphQL data is being generated from gatsby-transformer-json

Never mind, i ended up building a source plugin for my use case

Never mind, i ended up building a source plugin for my use case

Can you provide a link for the source plugin? I have the same problem. Thank you

@AleC77 it is currently part of my private repository. It works for my use case but i think it would need more work for it be useful to others.

Can you send me a short piece of code of that? I am becoming crazy to find a solution. It looks it is impossible with graphql filter the content of json file for me

@AleC77 have a look at what this module does with create node - https://github.com/GraphCMS/gatsby-source-graphcms/blob/master/src/util.js and then look at this tutorial - https://www.gatsbyjs.org/docs/source-plugin-tutorial/

You basically need to take the JSON, loop over it and create a gatsby node.

forEach(data, (value, key) => {
        const type = extractTypeName(key);
        forEach(value, (obj) => {
          const { id } = obj;

          const jsonNode = JSON.stringify(obj);
          const gatsbyNode = {
            id,
            ...obj,
            parent: null,
            children: [],
            internal: {
              type: type,
              content: jsonNode,
              contentDigest: createContentDigest(obj)
            }
          };

          createNode(gatsbyNode)
        });
      });

Thank you so much for the help @senorgeno

Was this page helpful?
0 / 5 - 0 ratings