Let Them Tell You No

As a recent college graduate who has a job teaching English in Spain, I am probably the poster child for avoiding the real world. However, I recently decided to start applying for jobs back in the…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




How you can use a GraphQL API for database administration

A recent discussion at graphql-europe made me realize that GraphQL would make for an amazing API for database administration.

You know that plethora of functions and options to control details from security, indexing, metadata, clustering, and other operations?

I used the trip home on the train to build a GraphQL admin endpoint for Neo4j, exposing all available procedures either as queries or mutations. Using Kotlin, this was fortunately a matter of only a few lines (200) of code. And it worked surprisingly well.

If you know of any other database that exposes its admin-API via GraphQL, please let me know in the comments — I’d love to have a look.

And if you get inspired to base some of your work on this idea, I’d be honored, even more so with attribution :)

An administrative query against the database API

The endpoint is not limited to built-in procedures. External libraries like APOC, graph-algorithms, or neo4j-spatial are automatically exposed.

In my book, the biggest benefit is the self documenting nature of GraphQL APIs based on the strict schema provided.

The strong typing, documentation, and defaults for both input and output types increase the clarity and reduce the number of trial-and-error attempts. The custom selection of output fields and optional deeper traversal of result structures allows for quick customizations of what you want to retrieve.

With the clear separation into read queries and write mutations, it is easy to reason about the impact of a call.

And of course the amazing auto-complete with inline help and the automatically available documentation in GraphiQL and GraphQL-Playground make interacting with such an API a joy. 🎉

Parameterizing all inputs and limiting result sizes is just icing on the 🎂.

Another advantage is that you can combine multiple queries into a single call. All relevant information for a full screen is retrieved in a single request.

Of course you can use all the available GraphQL tools like middleware or libraries for quickly building front-end applications (apollo-tools, React, semantic-ui, victory, etc.). That allows you to integrate these APIs quickly into your monitoring/administration scripts or dashboards.

The necessary graphql-schema is built from the available user-defined-procedures deployed in Neo4j.

You have to explicitely allow procedures to be exposed via the config setting graphql.admin.procedures.(read/write) with either Neo4j procedure syntax or admin-endpoint field names. For example, you could set it to:

In 2016, Neo4j 3.0 got a neat new extension point. You could provide annotated Java methods as user defined procedures, which then were callable either stand-alone or as part of your database queries. As our (React-based) Neo4j-Browser moved from HTTP to a binary transport, the original management REST-APIs were augmented with procedures providing the same functionality.

Ever since, a large amount of functionality has been moved to procedures and functions, giving us a broad selection of things to expose via GraphQL.

To construct the schema, I iterated over the available procedures, creating one field for each procedure.

I took the named procedure parameters as input arguments and used custom output types (per procedure) holding the returned columns. Input parameters with default values could be nullable, the others are defined as non-null. Procedure descriptions turned into field descriptions, and the deprecation information was also transferred.

I mapped basic scalar types and lists directly to GraphQL types.

Only for the Map (dict/object) type did I have to map to a List<Attribute> where each attribute is

which worked suprisingly well both for inputs and outputs.

Using the Attribute list for maps/dictionaries, both as input and output

Similarly, I created custom types for Node, Relationship and Path.

For these four custom types, I added the appropriate (de-)serialization code. All other unknown types were rendered to strings.

The resolver for each field just executes the wrapped procedure with the input arguments from the environment. The results are then mapped to the output type fields (optionally transformed) and returned to the endpoint.

Based on their metadata, I combined the fields into object types for Queries and Mutations, respectively.

And that was basically it.

I was surprised myself when I fired up GraphiQL after deploying the extension that I was able to intuitively call any of the queries and mutations without hiccups.

My biggest challenge is the lack of namespaces in GraphQL. While you can substructure queries nicely with nested types, the same is not available for mutations.

To keep the API naming consistent across both, I decided not to substructure queries and like mutations, and instead joined the capitalized parts of the namespace and procedure name together.

So db.labels turns into dbLabels .

Another slight challenge was the missing information about read vs. write operations in the DBMS and SCHEMA scopes of Neo4j procedures. So I had to use a whitelist to determine "read-only" ones, which of course is not sufficient.

Something that other API technologies don’t have built in, and which is really cool, is the ability to choose and pick any number of queries or mutations you want to run in a single request.

If necessary, you can even alias multiple invocations of the same query with different parameters (think statistics per database).

Run multiple API operations in a single request.

And you can even run graph-algorithms or cypher statements as part of this API, which is kinda cool.

Run a “Cypher” query.
Run a “graph-algorithm” procedure

Currently, I only directly expose the procedures parameters and results to the users. Going forward, it would be nice to derive higher level types that offer their own (dynamic) query fields, like

I would love 💕 a bunch of monitoring and management mobile-, web-apps and command-line-clients to be built on top of this management API.

Happy hacking! — Michael

Add a comment

Related posts:

Introducing flexible working hours

Why we decided to let got of our core working house in favour of a completely flexible work schedule

7 Big Mistakes Guys Make When They Try to Be Dominant in Bed

That makes a lot of guys nervous because they’re not sure how to approach it. They have a vague idea of what it means to be dominant but they don’t know how to have sex in a way that makes her feel…

OYO Data Science

Forecasting is a wide topic. It is a process of making predictions based on previous data. This was one of the projects I was working on my job as a member of Data Science. Now the problem statement…