Apollo-server: Resolving Union Type on different Resolver

Created on 19 Sep 2017  路  1Comment  路  Source: apollographql/apollo-server

Taking this scheme:

union Vehicle = Airplane | Car

type Airplane {
     title: String
     wingSpan: Int
}

type Car {
    title: String
    wheels: Int
}

type Person {
    vehicle: [Vehicle!]
}

With this query:

person {
     vehicles {
         ... on Car {
            title
            wheels 
         }
        ... on Airplane {
            title
            wingSpan 
         }
     }
}

And these resolvers:

// vehicle-resolver.js
export default {
    Vehicle: {
        __resolveType(obj) {
            if (obj.wheels)  {
                return "Car"
            } else {
                return "Airplane"
            }
        }
    }
}

// person-resolver.js
export default {
    Person: {
        vehicles(obj, args, context) {
            // Am I resolving a car or an airplane now - or even both?
            // I need to ask my CarService with `obj.personId` or my AirplaneService also with `obj.personId` but I only want to query it if the query is asking for it.
        }
    }
}

My question is that on my Person -> vehicles(...) I am unsure when I should query my service for getting the cars and when I should query my service for finding airplanes - or both?

The vehicles(...) does not give any information on what type(s) it tries to resolve?

鈦夛笍 question

Most helpful comment

If I understand your question correctly, you should query both and return all cars and airplanes that fits to the Person's vehicles query.
Then the __resolveType resolver would run for each result to provide GraphQL with the right type for each result.
Then with that information GraphQL would be able to return to the client the right selection set for each result.

Few things to make clear just to make sure we are on the same page:

The client does not determine if it queries for a specific type and doesn't know what type it will get, that's why the client places a query that handles both cases.
The vehicles resolver will return an array that may include all types on the union, the client's inline fragments as a switch/case statement for each result and the __resolveType resolver as providing the switch/case statement with the condition variable for each result.

If in the vehicles resolver you already know what the type of each result is, you can attach it to the result and simply return it in the __resolveType resolver but sometimes that creates complexity as those results will go through the whole resolver tree of the query and might affect logic in other resolvers.
So keep the logic inside __resolveType can help to keep handling union types logic contained in one place.

Maybe I wrote too much things you already knew, so let me know if that's not your question at all :)

>All comments

If I understand your question correctly, you should query both and return all cars and airplanes that fits to the Person's vehicles query.
Then the __resolveType resolver would run for each result to provide GraphQL with the right type for each result.
Then with that information GraphQL would be able to return to the client the right selection set for each result.

Few things to make clear just to make sure we are on the same page:

The client does not determine if it queries for a specific type and doesn't know what type it will get, that's why the client places a query that handles both cases.
The vehicles resolver will return an array that may include all types on the union, the client's inline fragments as a switch/case statement for each result and the __resolveType resolver as providing the switch/case statement with the condition variable for each result.

If in the vehicles resolver you already know what the type of each result is, you can attach it to the result and simply return it in the __resolveType resolver but sometimes that creates complexity as those results will go through the whole resolver tree of the query and might affect logic in other resolvers.
So keep the logic inside __resolveType can help to keep handling union types logic contained in one place.

Maybe I wrote too much things you already knew, so let me know if that's not your question at all :)

Was this page helpful?
0 / 5 - 0 ratings