Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to model recursive data structures in GraphQL

Tags:

graphql

I have a tree data structure that I would like to return via a GraphQL API.

The structure is not particularly large (small enough not to be a problem to return it in one call).

The maximum depth of the structure is not set.

I have modeled the structure as something like:

type Tag{     id: String!     children: [Tag] } 

The problem appears when one wants to get the tags to an arbitrary depth.

To get all the children to (for example) level 3 one would write a query like:

{ tags { id children { id children { id } } } }

Is there a way to write a query to return all the tags to an arbitrary depth?

If not what is the recommended way to model a structure like the one above in a GraphQL API.

like image 295
raduw Avatar asked Jun 25 '17 13:06

raduw


People also ask

What data structure does GraphQL use?

Your GraphQL server uses a schema to describe the shape of your available data. This schema defines a hierarchy of types with fields that are populated from your back-end data stores. The schema also specifies exactly which queries and mutations are available for clients to execute.

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.

Does GraphQL use graph data structure?

Graphs are the core reason why GraphQL is such a great choice to build and consume APIs. On the one hand, graphs allow developers to model the data in a natural way using directional relationships and hierarchies. The GraphQL Schema is a direct representation of a problem space based on natural language.


Video Answer


1 Answers

Some time ago I came up with another solution, which is the same approach like @WuDo suggested.

The idea is to flatten the tree on data level using IDs to reference them (each child with it's parent) and marking the roots of the tree, then on client side build up the tree again recursively.

This way you should not worry about limiting the depth of your query like in @samcorcos's answer.

schema:

type Query {     tags: [Tag] }  type Tag {     id: ID!     children: [ID]     root: Boolean } 

response:

{      "tags": [         {"id": "1", "children": ["2"], "root": true},          {"id": "2", "children": [], "root": false}     ]  } 

client tree buildup:

import find from 'lodash/find'; import isArray from 'lodash/isArray';  const rootTags = [...tags.map(obj => {...obj)}.filter(tag => tag.root === true)]; const mapChildren = childId => {     const tag = find(tags, tag => tag.id === childId) || null;      if (isArray(tag.children) && tag.children.length > 0) {         tag.children = tag.children.map(mapChildren).filter(tag => tag !== null);     } } const tagTree = rootTags.map(tag => {     tag.children = tag.children.map(mapChildren).filter(tag => tag !== null);     return tag; }); 
like image 169
tlenex Avatar answered Oct 03 '22 22:10

tlenex