Getting Started with Neo4j and GraphQL
Whereas GaphQL usually requires you to write resolvers for each operation Neo4j has started two projects on Github which provide "auto-translation" from GraphQL queries to Neo4j's Cypher queries and thus saves the effort to write custom resolvers. And on top there is only a single query to the database.
Although both neo4-graphql
and neo4-graphql-js
are still in early development it is amazing to see that without much effort in the backend you can provide a lot, varying, and nested data to your frontend without the need to write custom resolver for each GraphQL operation type
(e.g. queries or mutations). The approach is comparable to postgraphql
which translates a PostgreSQL schema to a GraphQL schema.
New to GraphQL and/or Neo4j? Check out this DZone RefCard or one of these two great videos (webinar or online meetup) by @lyonwj and come back for the rest of this intro.
Update: A lot has happened since this post was written ... so for the current features really/currently available please refer to:
- releases for
neo4-graphql
and - changelog and Announcing New Features In neo4j-graphql.js for
neo4-graphql-js
... and ignore the ones mentioned here.
Basic Setup
All you need is a Neo4j
instance with a database and - if using neo4-graphql-js
- a NodeJS
instance. Both are available as official Docker images.
Overview
You could of course set something up yourself, see the GRAND stack e.g., but regarding the two projects already provided by Neo4j there are basically two options:
- An embedded GraphQL server as a db extension (
neo4-graphql
), - or an external GraphQL server based on NodeJS (
neo4-graphql-js
).
neo4-graphql
The Kotlin based neo4j-graphql
can be installed as a Neo4j server extension to act as a GraphQL endpoint so that your Neo4j server is the GraphQL server. It then turns GraphQL queries and mutations into Cypher statements and executes them on the Neo4j server.
All you need to do is copy the appropriate .jar
file for your server version to the Neo4j plugins
directory and set the Neo4j config
to allow the plugin as yet unmanaged extension
. A basic Dockerfile
would then look like this:
FROM neo4j:latest
COPY neo4j-graphql-3.3.0.0.jar /var/lib/neo4j/plugins
RUN echo 'dbms.unmanaged_extension_classes=org.neo4j.graphql=/graphql' | tee -a /var/lib/neo4j/conf/neo4j.conf
CMD ["neo4j"]
After building the image and running the container you can either POST
your own schema to /graphql/idl
or let the extension build the schema from the graph.
For easy testing you could use graphiql
and if you are testing neo4j-graphql-js
as well (see below) you could just add another server.use
statement for this Neo4j-based GraphQL endpoint to the example movies.js
(note the IP as seen from the client-side and the trailing slash in the URL).
server.use('/neo4j-graphiql', graphiqlExpress({
// IP is the external Docker host IP as seen by your browser
endpointURL: 'http://192.168.178.28:7474/graphql/',
// Note the trailing slash in the URL
passHeader: 'Authorization: "Basic bmVvNGo...="',
query: `{
}`,
}));
(Although the movies.js example
uses another, extended movie db you can use the default Neo4j Movie DB as Neo4j now is your GraphQL server.)
For the default Neo4j Movie DB the auto-created schema for queries
looks like that:
And as neo4-graphql
already supports basic mutations it also gives you the following mutations
:
Summing up: neo4-graphql
is a Neo4j server extension making Neo4j itself the GraphQL API endpoint. It can accept a custom schema or create one from the existing db and it already supports mutations.
neo4-graphql-js
In contrast the NodeJS based neo4j-graphql-js
does not support mutations (yet) and is completely external to Neo4j. It is to be used with a stand-alone (e.g. graphql-server-express
based) GraphQL server which talks to the Neo4j sever via the js
neo4j-driver
. As of now you also need to provide your own schema.
However, you do not need to write custom resolvers for each GraphQL operation and you can use a @cypher schema directive
to annotate fields
with the result of the given cypher query
(for that to work you need to add the appropriate APOC procedure library for your version to Neo4j plugins
directory):
FROM neo4j:latest
COPY apoc-3.3.0.1-all.jar /var/lib/neo4j/plugins
RUN echo 'dbms.security.procedures.unrestricted=apoc.trigger.*,apoc.meta.*' | tee -a /var/lib/neo4j/conf/neo4j.conf
CMD ["neo4j"]
A basic Dockerfile
for the NodeJS container could look like this (the instructions assume that you forked
the Github repo and might slightly change if you install it via npm
):
FROM node:boron-slim
# context secrets
ENV NEO4J_URI="bolt://<yourNeo4jContainer>:7687"
ENV NEO4J_USER="neo4j"
ENV NEO4J_PASSWORD="<yourNeo4jPassword>" # don't use sensitive ENVs with public/published images
RUN npm install express -g
WORKDIR /path/to/neo4j-graphql-js
# Only on first run after forking the Github repo
# RUN npm install
RUN apt-get autoremove -y \
&& apt-get autoclean -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# 9229 is only for debugging
EXPOSE 3000 9229
USER node
CMD ["npm", "start"]
You then need to create a file which follows the example movies.js
with:
- your own
schema
(according to your database schema), - a config for the Neo4j
driver
andserver
statements for thegraphql
andgraphiql
endpoints (these can be the same as in themovies.js
) - Optionally you can also add another
neo4j-graphiql
endpoint as described above forneo4-graphql
(you can then use both within one setup) - Optionally (only if you forked the Github repo) change your
package.json
start script
to"nodemon ./example/graphql-tools/<yourFile>.js --exec babel-node -e js --inspect"
After building the images and running the containers you have a full setup for neo4j-graphql
and neo4j-graphql-js
in only two docker containers for testing/comparing purposes.
Summing up: The neo4-graphql-js
is another way to give your Neo4j sever a GraphQL API. It is used in a stand-alone server, completely independent of the Neo4j instance which requires a NodeJS sever. As of now it only supports basic read queries
, but no mutations
. However, in the long run it might prove more flexible and easier to configure then a prepackaged server extension.
Summary
Both neo4j-graphql
and neo4j-graphql-js
are still in early development and are about to change. However, already now they offer significant benefits such as especially:
- Always sending a single query to the database
- And no need to write queries for each resolver
In fact it was amazing to see how little effort it took in the backend to provide various data to the frontend. And despite the early development stage, some rough edges and bugs it was fun working with it.
Beyond that it pretty quickly became clear/tangible where the advantages of GraphQL
over REST
are - at least if you combine two technologies which both regard data as a graph and whose operations (on sub-trees within it) thus can easily be translated.
Update: There is also a follow-up blog post now available: Using and Accessing neo4j-graphql with NodeJS
Further Information
GraphQL:
http://graphql.org
http://graphql.org/code/
Neo4j:
https://github.com/neo4j-graphql
https://github.com/neo4j-graphql/neo4j-graphql
https://github.com/neo4j-graphql/neo4j-graphql-js
https://neo4j.com/developer/graphql/
DZone RefCard:
https://dzone.com/refcardz/an-overview-of-graphql
Videos:
https://go.neo4j.com/building-a-graphql-service-backed-by-neo4j-lp.html
https://youtu.be/0EmZjheYv-U
GRANDstack:
http://grandstack.io/
Example Launchpad:
(with the advanced movie db used in movies.js
)
https://launchpad.graphql.com/n59x9mw47
Data Modelling Guide:
https://www.graph.cool/docs/reference/database/data-modelling-eiroozae8u/
Using and Accessing neo4j-graphql with NodeJS:
https://daten-und-bass.io/blog/using-and-accessing-neo4j-graphql-with-nodejs/