Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo/GraphQL field type for object with dynamic keys

Let's say my graphql server wants to fetch the following data as JSON where person3 and person5 are some id's:

"persons": {   "person3": {     "id": "person3",     "name": "Mike"   },   "person5": {     "id": "person5",     "name": "Lisa"   } } 

Question: How to create the schema type definition with apollo?

The keys person3 and person5 here are dynamically generated depending on my query (i.e. the area used in the query). So at another time I might get person1, person2, person3 returned. As you see persons is not an Iterable, so the following won't work as a graphql type definition I did with apollo:

type Person {   id: String   name: String } type Query {   persons(area: String): [Person] } 

The keys in the persons object may always be different.

One solution of course would be to transform the incoming JSON data to use an array for persons, but is there no way to work with the data as such?

like image 579
Andru Avatar asked Oct 04 '17 10:10

Andru


People also ask

What are key args in Apollo GraphQL for?

You can define a completely different format for a field's storage key by providing a custom function to keyArgs . This function takes the field's arguments and other context as parameters, and it can return any string to use as the storage key (or a dynamically-generated keyArgs array).

What is __ Typename in GraphQL?

The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).

What are the three types of operations in GraphQL?

There are three types of operations that GraphQL models: query – a read‐only fetch. mutation – a write followed by a fetch. subscription – a long‐lived request that fetches data in response to source events.

What is scalar type in GraphQL?

GraphQL's Scalar TypesInt: A signed 32‐bit integer. Float: A signed double-precision floating-point value. String: A UTF‐8 character sequence. Boolean: true or false. ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache.


1 Answers

GraphQL relies on both the server and the client knowing ahead of time what fields are available available for each type. In some cases, the client can discover those fields (via introspection), but for the server, they always need to be known ahead of time. So to somehow dynamically generate those fields based on the returned data is not really possible.

You could utilize a custom JSON scalar (graphql-type-json module) and return that for your query:

type Query {   persons(area: String): JSON } 

By utilizing JSON, you bypass the requirement for the returned data to fit any specific structure, so you can send back whatever you want as long it's properly formatted JSON.

Of course, there's significant disadvantages in doing this. For example, you lose the safety net provided by the type(s) you would have previously used (literally any structure could be returned, and if you're returning the wrong one, you won't find out about it until the client tries to use it and fails). You also lose the ability to use resolvers for any fields within the returned data.

But... your funeral :)

As an aside, I would consider flattening out the data into an array (like you suggested in your question) before sending it back to the client. If you're writing the client code, and working with a dynamically-sized list of customers, chances are an array will be much easier to work with rather than an object keyed by id. If you're using React, for example, and displaying a component for each customer, you'll end up converting that object to an array to map it anyway. In designing your API, I would make client usability a higher consideration than avoiding additional processing of your data.

like image 91
Daniel Rearden Avatar answered Oct 16 '22 02:10

Daniel Rearden