What is GraphQL?

The fundamentals of GraphQL, its operational mechanics, and how it compares to other query languages like SPARQL and traditional RESTful approaches.

GraphQL, the Graph Query Language, is a robust alternative to traditional REST APIs, offering precise and flexible data retrieval capabilities. It is more flexible than a standard API and less complicated than SPARQL, while retaining some of the stronger points of both approaches. GraphQL is specifically targeted at frontend development. It is easier to use, self-documenting, and provides full control over the response contents. 

Advantages Over REST

Unlike REST, which requires loading of data from multiple URLs, GraphQL APIs get all the data your application needs in a single request. Apps using GraphQL can be quick even on slow mobile network connections. GraphQL also saves bandwidth by allowing developers to pinpoint exactly the data required, and nothing more.

A standard request on a REST endpoint always returns what’s programmed to be fetched; there is a strong contract between the server and the client. In GraphQL, as part of the operation declaration — also known as document — the client must specify exactly what it expects to be fetched.

Comparisons with SPARQL

While both GraphQL and SPARQL are powerful in querying complex data systems, they serve slightly different purposes. SPARQL is designed to query RDF databases. It is highly flexible and can query complex relational structures. 

In contrast, GraphQL simplifies the process with less verbose and complex queries but does so at the cost of some flexibility found in SPARQL. In particular, it trades off some of the graph navigation capabilities of SPARQL to achieve a much simpler syntax. GraphQL queries and responses are both JSON. Requests are executed over a REST API, just like SPARQL or a simple endpoint. GraphQL offers the full range of create read, update, delete operations (CRUD), as well as subscriptions.

GraphQL operations

Introspection

One of the most significant features of GraphQL is its introspection system. This feature allows clients to query which queries are currently supported by the API and how the system expects those queries to be called. This capability is built into the GraphQL system, enabling automated documentation and powerful, user-friendly tooling around API capabilities.

Technically, each introspection operation is considered a query. GraphQL’s introspection capability is crucial and sets it apart from SPARQL, which has no built-in method to examine the data model.

While RDF data and SPARQL can work without ontologies, GraphQL is, essentially, strongly typed. All objects and literals need to have a specific type, which has static relationships with the rest of the data model. Introspection allows you to retrieve metadata about the way in which those relationships are formed.

GraphQL’s strong typing lets it handle multiple data types and structures. It supports scalar types, objects, enums, and lists, allowing for detailed data structuring and manipulation within queries. GraphQL’s type system makes it easier to formulate complex, hierarchical data relationships than traditional RESTful services.

Strong typing means that you have a reliable source of information that is easy to validate. It doesn’t permit easy switching of datatypes, but that’s usually not an issue with most data lakes.

Queries

These correspond to the READ operation in CRUD (Create, Read, Update and Delete). You can fetch multiple objects, as well as nested data structures with a single query, reducing the need for multiple API calls. You also have the capability to select exactly what you want to fetch.

Like SPARQL, you have a full range of filters, limits and offsets. You can also extract parts of your query in a “fragment” to avoid repetition. Some fields can be aliased, changing their name. Filtering can be done both at the root level and for specific fields. For example, the query above specifies that three characters who have an eye color are fetched from the database. It further refines that the value of the eyeColor field needs to be returned if and only if the character happens to be blue-eyed.

It is important to note that queries execute “bottom-up”. That is, fields are fetched first and the whole object is returned after all fields are fetched. A missing value for a required field can, in turn, lead to the whole object being removed from the result set.

Mutations

Mutations allow you to INSERT, UPDATE and DELETE data. They follow largely the same principles and syntax as queries. Just like queries, mutations have to return objects — in their case, the data that was changed. The values you are changing are passed as mutation attributes. Mutations, unlike queries, are executed sequentially to avoid deadlocks.

A single mutation can modify multiple objects. Due to strong typing, validation is easy to achieve and can be backed by SHACL and frontend checks.

Subscriptions

Subscriptions are operations that allow you to get real-time updates from the server. They maintain a steady connection over an open web socket. When a change happens in the data, the client gets a new response from the server. Note that this is related to changes in the object as a whole — a change in field X, which you don’t necessarily return as output from the subscription, would cause a new notification. In structure, subscriptions function exactly the same as queries.

Real-world Applications and Challenges

GraphQL has been widely adopted by many organizations seeking to improve their applications’ responsiveness and data interaction capabilities. The strong federation support is one of its main advantages. GraphQL queries are easy to parallelize. GraphQL schemas can be “stitched” together or “extended”. This gives the end-user a holistic, opaque view of the entire data model. They don’t have to be familiar with the different constituent parts of the data and can have a singular unified access to it. This is made easier by the introspection system that keeps a unified schema constantly up to date.

Of course, GraphQL is not without challenges. The query parallelism capability and complexity, coupled with the lack of native graph traversal can lead to the “N+1 problem”. In it, the server makes multiple nested calls to databases. If each level obtains a nested object, which, in turn, obtains its own nested objects, a seemingly simple query can explode exponentially, only for the whole result to be nulled at a late stage due to a missing required field.

Joining RDF and GraphQL

In order to bring the flexible information of RDF into the strongly-typed GraphQL world, we require a mapping. Ontotext’s tools come with a mapping language called the Semantic Objects Modeling Language (SOML). It is a simple language for describing business objects (also called business entities, or domain objects in Domain-Driven Design), which are handled using semantic technologies and GraphQL. 

SOML is the language of Ontotext’s Semantic Objects and Semantic Search. SOML maps GraphQL operations to SPARQL. This way, users can enjoy the capabilities of RDF while benefiting from the approachability of GraphQL. SOML can be auto-generated from OWL ontologies or SHACL and annotated manually, making the transformation as painless as possible.

GraphQL and Your Applications 

GraphQL stands out as a transformative technology in the realm of API design and data querying. With its robust, flexible capabilities and strong typing system, it offers an appealing solution for developers looking to build efficient, scalable applications. 

As the technology matures, it is expected to solve more complex data retrieval needs, making it a staple in modern web development. By understanding these fundamentals, developers can better harness the power of GraphQL to enhance their applications and user experiences.  

If you want to dive deeper with GraphQL, read this article about embedding graphs in enterprise architectures via GraphQL, Federation and Kafka.

Ontotext Newsletter