Quite new to GraphQL and lighthouse library, don’t be too harsh.
Since I can’t use any models because my data source is an API. I’m trying to create a custom resolver that will pass data to a service who will do everything necessary to retrieve data from the API.
And it constantly returns me this error: "Field "address" of type "[Address!]" must have a sub selection.",
I believe it’s because of the fact I don’t use models(just a wild guess)
So far my schema looks like this:
type Query { address(address: String!): [Address!] @field(resolver: "Address@resolve") } type Address { fullAddress: String! lowestId: Int! }
And the mentioned resolver:
public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): array { return array_map( function ($address): array { return [ 'fullAddress' => $address->getFullAddress() ]; }, $this->service->getAddress($args['address']) ); }
Thank you in advance!
Advertisement
Answer
The error is not even specific to Lighthouse, any GraphQL server will produce a similar error for what you are trying to do. I assume you are trying a query like this:
{ address(address: "foo") }
Consider the graph in GraphQL: your server describes available data types and relations between them, forming a graph. Each type could have fields that lead to another type, and that type to another type, and so on. Those references can even form cycles. At some points, the graph may end: types such as scalar values mark the leaves of the graph.
Now, how does a server know which part of the graph you want to see and it should resolve? Through a query: a subselection of a part of that graph. That naturally limits how deep the server must go, it can do the minimal amount of work to return the parts of the graph you queried for.
One rule of queries is that you must always end up at leaf nodes. This is where the error message comes into play: the server sees that Address
is not a leaf type and thus asks you to specify how deep you want to traverse the graph. A working query could be:
{ address(address: "foo") { fullAddress } }