Overview About GraphQL Queries GraphQL as a Contract Schema GraphQL and Neo4j Neo4j GraphQL extension GraphQL Community Graph Hackathon What is a Community Graph? Hackathon GraphQL Support Resources Raw Data Access About GraphQL GraphQL is a specification for querying a… Learn More →

About GraphQL

200px GraphQL Logo.svg

GraphQL is a specification for querying a slice of an application graph, retrieving a tree of data that perfectly matches a front-end view, regardless of was that data was pulled from. It covers tree-based read-queries, mutations for updates and subscriptions for live updates.

Queries

Queries form a tree structure, based upon entities and relevant attributes. Any of those can take parameters (e.g for filtering or pagination) and directives.

GraphQL example query
query {
   Movie(title:"The Matrix") {
      title
      released
      tagline
      actors {
         name
         born
      }
   }
}
GraphQL example result
{
   "Movie": [{
      "title": "The Matrix",
      "released": 1999,
      "tagline": "Welcome to the Real World",
      "actors": [{
         "name": "Keanu Reeves",
         "born": 1964
         }, {
         "name": "Carrie-Anne Moss",
         "born": 1967
         }, {
         "name": "Laurence Fishburne",
         "born": 1961
         }
      ]
   }]
}

GraphQL as a Contract

In this regard it is a contract between front-end and back-end, based on the agreed upon type system which forms an application data model in the form of a graph.

It decouples the front-end from the back-end data source(s), which allows you to change both independently as the type system stays consistent. Each query from the front-end is using that type system to define in a fine grained way which data it is interested in.

There is no prescription how and where the data in the back-end comes from, it can be anything from databases, to APIs, from third party systems to in-memory representations, and even code or static assets.

GraphQL queries return data in a tree-form that perfectly matches the front end view hierarchy. If the application data is a graph, then the perfect back-end is a Graph Database with native support for resolving GraphQL queries: Neo4j.

Schema

The typesystem is often declared in schema (IDL) files which contain entities, their attributes, interfaces, enumerations, but also mutations and subscriptions. The schema can be extended with custom directives and types that allow specific extensions of the core language.

GraphQL example schema
type Movie {
    title: String!
    released: Int
    tagline: String
    actors: [Person]
}

type Person {
    name: String!
    born: Int
    movies: [Movie]
}

GraphQL and Neo4j

Neo4j GraphQL extension

neo4j graphql logo

We wanted to combine the power of Neo4j and GraphQL by making it super-easy to take an IDL schema OR an existing graph and serve a native GraphQL backend from it.

With the information from the schema we’re able to generate a single query against the backing graph database. During development both Neo4j’s property graph model as well as the Cypher query language turned out to be a great fit for the GraphQL features we’re supporting so far.

You can grab the latest release our extension from here and drop it into any Neo4j 3.1.x server (in the plugins directory). After a restart you can either query your graph data using GraphQL directly or after posting an IDL file with the schema you like.

We added some neat features that we hope are useful and make your life easier.

We’re especially proud of the @cypher directive, the auto-generated mutations (create, update, delete), and the graphql.execute, graphql.idl and graphql.schema procedures.

Here is an example, how the schema definition above could / would be extended:

type Movie {
    title: ID!
    released: Int
    tagline: String

    actors: [Person] @relation(name:"ACTED_IN", direction:IN)

    director: Person @relation(name:"DIRECTED", direction:IN)

    recommendation(first:Int = 3): [Movie]
      @cypher(statement:"MATCH (this)<-[r1:REVIEWED]-(:User)-[r2:REVIEWED]->(reco:Movie)
                         WHERE 3 <= r1.stars <= r2.stars
                         RETURN reco, sum(r2.stars) as rating ORDER BY rating DESC")
}

interface Person {
    name: ID!
    born: Int
}

type Actor extends Person {
    name: ID!
    born: Int

    movies: [Movie] @relation(name:"ACTED_IN")
}

type Director extends Person {
    name: ID!
    born: Int

    movies: [Movie] @relation(name:"DIRECTED")
}

type Mutations {
    directed(movie:ID! director:ID!) : String
      @cypher(statement:"MATCH (m:Movie {title: $movie}), (d:Person {name: $director})
                         MERGE (d)-[:DIRECTED]->(m)")
}
schema {
   mutations: Mutations
}

Have a look at the following “feature” table, to see what else is “in the box”:

name information example

entities

each node label represented as entity

{ Person {name,born} }

multi entities

multiple entities per query turned into UNION

{ Person {name,born} Movie {title,released} }

properties (out)

via sampling property names and types are determined

{ Movie {title, released} }

field parameters

all properties can be used as filtering (exact/list) input parameters, will be turned into Cypher parameters

{ Movie(title:"The Matrix") {name,released} }

query parameters

passed through as Cypher parameters

query MovieByParameter ($title: String!) { Person(name:$name) {name,born} }

relationships

via a @relationship annotated field, optional direction

type Person { name: String, movies : Movie @relation(name:"ACTED_IN", direction:OUT) }

ordering

via an extra orderBy parameter

query PersonSortQuery { Person(orderBy:[name_desc,born_desc]) {name,born}}

pagination

via first and offset parameters

query PagedPeople { Person(first:10, offset:20) {name,born}}

schema first IDL support

define schema via IDL

:POST /graphql/idl "type Person {name: String!, born: Int}"

Mutations

create/delete mutations inferred from the schema

createMovie(title:ID!, released:Int) updateMovie(title:ID!, released:Int) deleteMovie(title:ID!)

createMoviePersons(title:ID!,persons:[ID!]) deleteMoviePersons(title:ID!,persons:[ID!])

Cypher queries

@cypher directive on fields and types, parameter support

actors : Int @cypher(statement:"RETURN sizethis)←[:ACTED_IN]-(")

Cypher updates

Custom mutations by executing @cypher directives

createPerson(name: String) : Person @cypher(statement:"CREATE (p:Person {name:{name}}) RETURN p")

extensions

extra information returned

fields are: columns, query, warnings, plan, type READ_ONLY/READ_WRITE,

In the repository, you can find a movies schmema and accompanying queries, that uses some of those features.

GraphQL Community Graph Hackathon

graphql community graph

What is a Community Graph?

We found it very helpful and inspiring to bring the people and activities of the GraphQL-Community into one database with a GraphQL-API endpoint.

It contains tweets, github-repositories, stackoverflow-questions and answers and meetup events and the users and tags related to them.

No matter where you are active, your contributions should be visible.

And everyone in the community should be able to find new content, recent topics, active people or new events easily.

graphiql.communitygraph

Hackathon

To learn more about what’s important to the GraphQL community, We’d love to challenge you!

We’re running a world-wide community Hackathon, starting now and running until end of day Monday, May 22.

Write a (mobile) demo, application, dashboard, visualization, timeline, react component, whatever you want against this GraphQL API, submit it here and also TWEET the link with #graphql #neo4j hashtags.

For the first 15 valid submissions we offer a prize (a pair of AirPods or equivalent amazon-gift-card).

Please submit your work in this survey and tell us about your experience building it and your thoughts about GraphQL.

If you fill out the survey above, we’ll send you a really cool graph t-shirt.

If you are attending GraphQL-Europe we’d love you to come by our booth and tell and show us in person.

Then you can get your t-shirt right away.

GraphQL Support

To demonstrate the combined power of a graph database (Neo4j) and GraphQL we also added the GraphQL extension to this server. Access the GraphQL community graph, including GraphiQL here.

After authorising you’ll be able to query the GraphQL community graph with your trusted tools like GraphiQL or Apollo-Client. You can also visualize the Schema using Voyager.

graphql community query leeb

graphql community voyager

You can find the schema for the data and several GraphQL queries and screenshots of your tools in action in this repository.

Resources

If you want to provide more feedback, just create an issue in any of our neo4j-graphql repositories, drop us an email or join neo4j-users Slack and ask in the #neo4j-graphql channel.

Raw Data Access

The raw graph data is publicly accessible here via the Neo4j Browser (http://107.170.69.23:7474 username/pwd: graphql/graphql).

community graphql cypher graph

community.graphql.cypher.table

If you are used to Neo4j you can use it right away by writing some Cypher statements. Here are (some suggestions).