Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL.js Node/Express: How to pass object as GraphQL query argument

My goal is to be able to pass an object as an argument in a GraphQL query.

Goal:

{
    accounts (filter: 
      {"fieldName": "id",
      "fieldValues":["123"],
      "filterType":"in"}){
        id
      }
 }

Error:

"message": "filterType fields must be an object with field names as keys or a function which returns such an object."

I've tried a few different approaches but this seems to be the closest to the potential solution.

Schema:

const filterType = new GraphQLObjectType ({
  name: 'filterType',
  fields: {
    fieldName: { type: GraphQLString },
    fieldValues: { type: GraphQLString },
    filterType: { type: GraphQLString },
  }
})

const QueryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    accounts: {
      type: new GraphQLList(accountType),
      args: {
        filter: { type: new GraphQLInputObjectType(filterType) },
      },
      resolve: (root, args, { loaders }) => loaders.account.load(args),
    },

  }),
});
like image 963
JTAN Avatar asked Mar 10 '17 16:03

JTAN


People also ask

How do you pass an argument in a GraphQL query?

When you're passing arguments in code, it's generally better to avoid constructing the whole query string yourself. Instead, you can use $ syntax to define variables in your query, and pass the variables as a separate map. . then(data => console.

Can you use GraphQL with Express?

Finally the Express server is created with a GraphQL endpoint: /graphql. To create the GraphQL endpoint first a new express instance is stored in app.

How do you pass two arguments in GraphQL query?

Multiple arguments can be used together in the same query. For example, you can use the where argument to filter the results and then use the order_by argument to sort them.


2 Answers

I have found the solution here. https://github.com/mugli/learning-graphql/blob/master/7.%20Deep%20Dive%20into%20GraphQL%20Type%20System.md#graphqlinputobjecttype

Schema:

const filterType = new GraphQLInputObjectType({
  name: 'filterType',
  fields: {
    fieldName: { type: GraphQLString },
    fieldValues: { type: GraphQLString },
    filterType: { type: GraphQLString },
  }
})

const QueryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    accounts: {
      type: new GraphQLList(accountType),
      args: {
        filter: { type: filterType },
      },
      resolve: (root, args, { loaders }) => {
        return loaders.account.load(args)},
    },
  }),
});

Problem was in the query, I had the both the keys and values as strings in the object argument.

Correct Query:

{
  accounts(filter: {fieldName: "id", fieldValues: "123", filterType: "in"}) {
    id
  }
}
like image 163
JTAN Avatar answered Sep 18 '22 13:09

JTAN


You don't define filterType as an object type then wrap it in an input type, you literally create it as an input type:

const filterType = new GraphQLInputObjectType({
  name: 'filterType',
  fields: {
    fieldName: { type: GraphQLString },
    fieldValues: { type: GraphQLString },
    filterType: { type: GraphQLString },
  }
})

const QueryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    accounts: {
      type: new GraphQLList(accountType),
      args: {
        filter: { type: filterType },
      },
      resolve: (root, args, { loaders }) => loaders.account.load(args),
    },
  }),
});

You'll also want to declare its type at query time, as illustrated in @piotrbienias's answer.

like image 44
Andrew Ingram Avatar answered Sep 19 '22 13:09

Andrew Ingram