Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structuring GraphQL types

Tags:

graphql

I've run into an issue while trying to extend my API to include a GraphQL endpoint. The application I'm working on is a kind of forum with Messages. A message can contain comments of type Message. If a message is a comment it has a parent of type Message. Simplified, the schema looks like this:

type Message {
  id: String
  content: String
  comments: [Message]
  parent: Message
}

type RootQuery {
  message(id: String): Message
  messages: [Message]
}

The problem with this schema is that it allows for queries like this:

{
  messages {
    comments {
      parent {
        comments {
          parent {
            comments {
              parent {
                id
                content       
              }
            }       
          }
        }   
      }
    }
  }
}

Keep in mind that I may want to allow for arbitrarily deep nesting of comments. In that case the following query should be allowed:

{
  messages {
    comments {
      comments {
        comments {
          id
          content
        }
      }
    }
  }
}

So, my question is this: Should I introduce a new type - Comment - to the API that do not know of its parent? Or are there any other ways of restricting this kind of unwanted behaviour?

Also, would the use of a Comment-type prohibit me from using the fragment messageFields on Message syntax in my queries? Perhaps this is the time to introduce interfaces to the schema?

Suggestion to a solution if I introduce the type Comment (I have not tried this):

interface Message {
  id: String
  content: String
  comments: [Message]
}

type DefaultMessage : Message {
  id: String
  content: String
  comments: [Comment]
  parent: Message
}

type Comment : Message {
  id: String
  content: String
  comments: [Message]
}

type RootQuery {
  message(id: String): Message
  messages: [Message]
}
like image 902
henkimon Avatar asked Sep 07 '15 16:09

henkimon


People also ask

What are the three types of operations in GraphQL?

GraphQL works by sending operations to an endpoint. There are three types of operations: queries, mutations, and subscriptions.

How is GraphQL structured?

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 is a type in GraphQL?

Character is a GraphQL Object Type, meaning it's a type with some fields. Most of the types in your schema will be object types. name and appearsIn are fields on the Character type. That means that name and appearsIn are the only fields that can appear in any part of a GraphQL query that operates on the Character type.

What other types can be used in a GraphQL schema?

The GraphQL schema language supports the scalar types of String , Int , Float , Boolean , and ID , so you can use these directly in the schema you pass to buildSchema . By default, every type is nullable - it's legitimate to return null as any of the scalar types.


1 Answers

Just in case anyone else ends up here wondering how to do recursive types in graphql-js, there's a useful hint in graphql-js's code:

 * When two types need to refer to each other, or a type needs to refer to
 * itself in a field, you can use a function expression (aka a closure or a
 * thunk) to supply the fields lazily.
 *
 * Example:
 *
 *     var PersonType = new GraphQLObjectType({
 *       name: 'Person',
 *       fields: () => ({
 *         name: { type: GraphQLString },
 *         bestFriend: { type: PersonType },
 *       })
 *     });
 *
 */

https://github.com/graphql/graphql-js/blob/master/src/type/definition.js#L274

like image 88
Marco Lüthy Avatar answered Oct 23 '22 14:10

Marco Lüthy