GraphQL pass args to sub resolve
Asked Answered
H

2

15

I have a relationship between User and Post. This is how I query the User Posts.

const UserType = new GraphQLObjectType({
  name: 'User'
  fields: () => ({
    name: {
      type: GraphQLString
    },
    posts: {
      type: new GraphQLList(PostType),
      resolve(parent, args , { db }) {
        // I want to get here the args.someBooleanArg
        return someLogicToGetUserPosts();
      }
    }
  })
});

The main query is:

const queryType = new GraphQLObjectType({
  name: 'RootQuery',
  fields: {
    users: {
      type: new GraphQLList(UserType),
      args: {
        id: {
          type: GraphQLInt
        },
        someBooleanArg: {
          type: GraphQLInt
        }
      },
      resolve: (root, { id, someBooleanArg }, { db }) => {
        return someLogicToGetUsers();
      }
    }
  }
});

The problem is the args in the resolve function of the UserType posts is empty object, how do i pass the args from the main query to sub resolves functions?

Hanleigh answered 27/9, 2016 at 18:49 Comment(0)
F
9

When resolving the root query you can use object assign to attach the argument to the user object returned. Then, on the user type, resolve the argument from the root value (first argument of resolve function).

Example:

const queryType = new GraphQLObjectType({
  name: 'RootQuery',
  fields: {
    users: {
      type: new GraphQLList(UserType),
      args: {
        id: {
          type: GraphQLInt
        },
        someBooleanArg: {
          type: GraphQLInt
        }
      },
      resolve: (root, { id, someBooleanArg }, { db }) => {
        return Promise.resolve(someLogicToGetUsers()).then(v => {
            return Object.assign({}, v, {
                someBooleanArg
            });
        });
      }
    }
  }
});

const UserType = new GraphQLObjectType({
  name: 'User'
  fields: () => ({
    name: {
      type: GraphQLString
    },
    posts: {
      type: new GraphQLList(PostType),
      resolve(parent, args , { db }) {
        console.log(parent.someBooleanArg);
        return someLogicToGetUserPosts();
      }
    }
  })
});
Flocculus answered 27/9, 2016 at 19:54 Comment(1)
Is there no native way to pass it as "args" to the sub query instead of altering the response object?Granthem
T
2

You can use the resolver fouth argument, info, to receive the desired variable - from Apollo docs:

Every resolver in a GraphQL.js schema accepts four positional arguments:

fieldName(obj, args, context, info) { result }

These arguments have the following meanings and conventional names:

obj: The object that contains the result returned from the resolver on the parent field, or, in the case of a top-level Query field, the rootValue passed from the server configuration. This argument enables the nested nature of GraphQL queries.

args: An object with the arguments passed into the field in the query. For example, if the field was called with author(name: "Ada"), the args object would be: { "name": "Ada" }.

context: This is an object shared by all resolvers in a particular query, and is used to contain per-request state, including authentication information, dataloader instances, and anything else that should be taken into account when resolving the query. If you're using Apollo Server, read about how to set the context in the setup documentation.

info: This argument should only be used in advanced cases, but it contains information about the execution state of the query, including the field name, path to the field from the root, and more. It's only documented in the GraphQL.js source code.

The info seems to be a very undocumented feature, but I'm using it now with no problems (at least until somebody decide to change it).

Here is the trick:

const UserType = new GraphQLObjectType({
  name: 'User'
  fields: () => ({
    name: {
      type: GraphQLString
    },
    posts: {
      type: new GraphQLList(PostType),
      resolve(parent, args , { db }, info) {
        // I want to get here the args.someBooleanArg

        console.log("BINGO!");
        console.log(info.variableValues.someBooleanArg);

        return someLogicToGetUserPosts();
      }
    }
  })
});
Tractable answered 14/5, 2019 at 19:50 Comment(2)
This is not correct, the args of the field are not the same as the variables of your query. You could have, for example ``` query($variableId: ID) { user(id: $variableId){ posts { // here you get info. variableValues.variableId, not user args.id } } ```Diachronic
this only works for named variables, if you use hard coded ones they dont show upBrittne

© 2022 - 2024 — McMap. All rights reserved.