0

I have some json data in file called countryData.json structured as so:

{
"info":"success",
"stats":
[{
    "id":"1",
    "name":"USA",
    "type":"WEST"
 },
 //...

I'm using graphQL to access this data. I have created an object type in the schema for countries using the following:

const CountryType = new GraphQLObjectType({
    name: "Country",
    fields: () => ({
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        type: { type: GraphQLString },
    })
});

I want to write a query that will allow me to access all of the elements of this array that have a certain "name" value(There can be multiple with the same name). I've written the following query, but it only returns the first match in the array:

const RootQuery = new GraphQLObjectType({
    name:"RootQueryType",
    fields:{
        country: {
            type: CountryType,
            args: { type: { name: GraphQLString } },
            resolve(parent, args){
                return _.find(countryData.stats, {name: args.name});
            }
        }
    }
});

The "_" comes from const _ = require('lodash');

Also, how can I just get every single item in the array?

ram
  • 39
  • 1
  • 1
  • 5

1 Answers1

1

I have not recreated the code, therefore I can not check if it would be executed correctly. This is code, that should work in my opinion (without trying). If you want to return array of elements you need to implement https://lodash.com/docs/#filter. Filter will return all objects from stats, which match the argument name. This will return correctly inside resolver function, however, your schema needs adjustments to be able to return array of countries.

  1. You need probably rewrite the arguments as follows as this is probably not correct. You can check out how queries or mutation arguments can be defined https://github.com/atherosai/express-graphql-demo/blob/feature/2-json-as-an-argument-for-graphql-mutations-and-queries/server/graphql/users/userMutations.js. I would rewrite it as follows to have argument "name"

    args: { name: { type: GraphQLString } }

  2. You need to add GraphQLList modifier, which defines, that you want to return array of CountryTypes from this query. The correct code should look something like this

    const RootQuery = new GraphQLObjectType({
      name:"RootQueryType",
      fields:{
        country: {
            type: CountryType,
            args: { name: { type: GraphQLString } },
            resolve(parent, args){
                return _.find(countryData.stats, {name: args.name});
            }
        },
        countries: {
            type: new GraphQLList(CountryType),
            args: { name: { type: GraphQLString } },
            resolve(parent, args){
                return _.filter(countryData.stats, {name: args.name});
            }
        }
      }
    });
    

Now if you call query countries, you should be able to retrieve what you are expecting. I hope that it helps. If you need some further explanation, I made the article on implementing lists/arrays in GraphQL schema as I saw that many people struggle with similar issues. You can check it out here https://graphqlmastery.com/blog/graphql-list-how-to-use-arrays-in-graphql-schema

Edit: As for the question "how to retrieve every object". You can modify the code in resolver function in a way, that if the name argument is not specified you would not filter countries at all. This way you can have both cases in single query "countries".

David Mraz
  • 545
  • 4
  • 8