Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving nested data in express GraphQL

I am currently trying to resolve a simple recipe list that has a reference to ingredients.

The data layout looks like this:

type Ingredient {
  name: String!
  amount: Int!
  unit: Unit!
  recipe: Recipe
}

type Recipe {
  id: Int!
  name: String!
  ingredients: [Ingredient]!
  steps: [String]!
  pictureUrl: String!
}

As I understand it, my resolvers should look like this: The first one resolves the recipes and second one resolves the ingredient field in the recipe. It can (from my understanding) use the argument provided by recipe. In my recipe object, the ingredient is referenced by id (int), so this should be the argument (at least that's what I think).

var root = {
  recipe: (argument) => {
       return recipeList;
  },
  Recipe: {
    ingredients: (obj, args, context) => {
        //resolve ingredients
    }
  },

These resolvers are passed to the app like this:

app.use('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true,
  rootValue: root,
}));

However, my resolver does not seem to be called. I would like the ingredients to be resolved on the fly when queried in my query.

The endpoint works, but as soon as I query for ingredients, an error with this message "message": "Cannot return null for non-nullable field Ingredient.name.", is returned.

When trying to log the incoming arguments in my resolver, I can see that it is never executed. Unfortunately, I can't find examples on how to do this with express-graphql when using it like I am.

How do I write seperate resolvers for nested types in express-graphQL?

like image 264
areiser Avatar asked Feb 26 '18 09:02

areiser


Video Answer


1 Answers

Only resolvers for queries and mutations can be defined through root, and even then this is bad practice. I'm guessing you're building your schema using buildSchema, which is generally a bad idea since the generated schema will only use default resolvers.

The only way to define resolvers for a field like ingredients when using plain GraphQL.js is to not use buildSchema. Instead of generating your schema from a string, you would define it programatically (i.e. defining a GraphQLSchema and all the types it uses).

Doing the above is a huge pain, especially if you already have your schema defined in a string or document. So the alternative option is to use graphql-tools' makeExecutableSchema, which lets you inject those resolvers into your type definitions like you're trying to do. makeExecutableSchema returns a GraphQLSchema object, so you can use it with your existing code (you don't have to change your middleware to apollo-server if you don't want to).

like image 175
Daniel Rearden Avatar answered Sep 26 '22 03:09

Daniel Rearden