A New Hope: The Rise of the Knowledge Graph

Navigating through the Star Wars universe with knowledge graphs, SPARQL and GraphQL

December 6, 2019 20 mins. read Jem Rayfield

It is a period of civil war. Rebel GraphQL developers strike from a hidden base and have won their first victory against the evil SPARQL empire. During the battle, however, it is discovered that Ontotext has secret plans to allow both GraphQL and SPARQL to co-exist, and flourish together, building the ultimate weapon, the ONTOTEXT PLATFORM! An armored Knowledge Graph platform with enough power to enrich an entire planet. Jem Rayfield races home aboard his starship, custodian of the stolen plans that can save your people and restore freedom within the enterprise….

Learn more about Ontotext Platform!

Star Wars Knowledge Graphs

Knowledge graphs represent information in a manner similar to how Luke Skywalker (a Human) understands information.

Rather than binding our data into the artificial and simplified format of a relational database, data stored in graphs mimic the intuitive way humans understand information. We inevitably connect information

Ontotext has built a Star Wars Knowledge graph using RDF in order that: 

  • Star Wars entities and relationships can be uniquely identified
  • Star Wars data can be joined with simplicity using RDFs standard model for data interchange, providing context and higher levels of abstraction, closer to human understanding
  • Additional Star Wars knowledge can be inferred from the Star Wars universe
  • Star Wars entities can be resolved and matched using vector spaces
  • Star Wars becomes searchable using complex expressive SPARQL queries
  • Star Wars provides a vocabulary for Text Analytics
  • Star Wars can be queried and mutated using GraphQL, with its galaxy of developer tools.

Navigating through the Star Wars universe…..it’s complex?

SPARQL and RDF are perceived by many to be complex, difficult and an unstable niche technology stack. Appearing by many to be conceived out of a scientific agenda.

But not everyone agrees…

“Powerful you have become, the dark side I sense in you.” – Yoda

Ontotext’s GraphDB is an enterprise-ready, high performance, scalable and simple to use database. It provides traversable graph visualizations simplifying access to the underlying data. Where possible it attempts to avoid some of the Semantic Web complexities/fundamentalism, providing tooling to ease data integration, data modeling, and information management.

SPARQL (GraphDB’s query language) a W3C standard is equivalent to relational algebra, from the point of view of expressiveness. Understanding the expressive power of the SPARQL query language is crucial to understand its capabilities and complexity. That is, what queries a user is able to pose, and the associated evaluation complexity. These issues should be central considerations when you choose a suitable Graph query language for your data. SPARQL is more than capable, expressive and able to satisfy many complex Graph use cases.

But…what do developers want? Many APIs are now built using GraphQL and JSON. “A query language for your API”. GraphQL is simple, declarative and powerful. GraphQL also has a large community with many tools, frameworks, and huge momentum. 

  • A GraphQL client specifies the data it needs, receiving only what it asks for and nothing more
  • GraphQL makes it easy to aggregate data from multiple sources using techniques such as federation
  • GraphQL uses a strong type system to describe its data, which is simple and declarative
  • Introspection is supported allowing clients to query and examine the schema. IDEs such as GraphiQL and GraphQL playground are also supported, with nice features such as query completion, etc.
  • GraphQL is hierarchical in nature, allowing users to define the shape of data that they want to be accessible
  • It’s a protocol and not a storage layer. Normally each data point is translated into a query or mutate function using resolvers.
  • It’s a simple facade over complex storage and query languages

GraphQL can provide a simple declarative lense across large RDF knowledge graphs providing developers with tooling that can bootstrap knowledge graph APIs. A declarative GraphQL service that provides quick, simple, consistent access to controlled query and mutation capabilities can enhance any developer’s toolset.

GraphQL used in combination with SPARQL’s underlying power, complexity and expressivity could be the answer to peace within the galaxy?

The Ultimate Weapon – Ontotext Platform

The Ontotext Platform vision, technology, and business are about making sense of text and data. Letting big knowledge graphs improve the accuracy of text analytics. Using text analytics to interlink and enrich knowledge graphs. Enabling better search, exploration, classification, and recommendation across diverse information spaces.

Stolen Ontotext Platform Plans

Stolen Ontotext Platform Plans

The Ontotext platform is currently undergoing some heavy refactoring. A new version 3.x will be released soon. The not so secret plans have been downloaded onto R2D2 for your inspection:

Ontotext Platform

At the core of the platform, rebuild is a new Semantic Object service.

A declaratively, configurable service for querying and updating knowledge graphs. Users can write powerful GraphQL queries that uncover deep relationships within the data while not having to be overly concerned about the underlying database query language. Data can be modified and validated against configured data shapes with simplicity and ease.

The Semantic Object service transpiles GraphQL queries and mutations into the platform’s different data storage layer query syntaxes. Queries and mutations are invoked, joined and validated, providing a simplified developer experience for those use-cases when GraphQL is enough.

The platform includes a number of performance optimizations to ensure optimal GraphQL query and mutation performance. For example, GraphQL invocation normally involves executing resolvers for each object property that is requested. Perhaps invoking a function to retrieve Star Wars characters and then for each character invoking another function to retrieve the Films in which the character appeared in, the classic N+1 query problem. The Ontotext Platform avoids this bottleneck to ensure GraphQL queries and mutations travel at hyperspace speed.

The Empire Strikes Back

So now let’s examine all the Star Wars data you’ve ever wanted. First taking a look under the hood at the raw RDF data. Then traversing the RDF graph using GraphDb visualizations and lastly running a SPARQL query.

Later in this blog post, you will be able to access the Star Wars data as JSON using a number of GraphQL example queries. After which you can draw your own conclusions as to which query protocol suits a particular use case best.

The Star Wars RDF data set includes:

  • Characters [voc:Character]
  • Species (Amphibian, Artificial, Insectoid, Mammal, Reptile) [voc:Species]
  • Films [voc:Film]
  • Planets [voc:Planet]
  • Spaceships [voc:Starship]
  • Vehicles [voc:Vehicle]

The data is enhanced and transformed from the publicly available SWAPI API.  Certain aspects of the SWAPI data model are much improved, supporting graph traversal, but also including a species classification which infers additional knowledge via RDFS reasoning.

The Star Wars RDF data is available to download.

Star Wars RDF – Data

Star Wars entities such as Luke Skywalker are modeled as RDF in order that they can be stored and queried within GraphDB. This particular RDF snippet describes the Star Wars character Luke Skywalker.

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<human/1> a voc:Human, voc:Mammal, voc:Sentient a voc:Character;
    rdfs:label "Luke Skywalker" ;
    voc:birthYear "19BBY" ;
    voc:eyeColor "blue" ;
    voc:film <film/1>, <film/2>, <film/3>, <film/6>, <film/7> ;
    voc:gender "male" ;
    voc:hairColor "blond" ;
    voc:height "172.0"^^xsd:float ;
    voc:homeworld <planet/1> ;
    voc:mass 77.0 ;
    voc:skinColor "fair" ;
    voc:starship <starship/12>, <starship/22> ;
    voc:vehicle <vehicle/14>, <vehicle/30> .

Luke Skywalker <human/1> is a voc:Human. Which by inference also implies that he is a voc:Mammal and a voc:Sentient. As a voc:Character he also appeared in the following voc:Films

An instance of a voc:Film such as A New Hope would be represented as follows:

@base <https://swapi.co/resource/> . 
@prefix voc: <https://swapi.co/vocabulary/> . 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<film/1> a voc:Film ;
    rdfs:label "A New Hope" ;
    voc:character <human/1> ;
    voc:director "George Lucas" ;
    voc:episodeId 4 ;
    voc:planet <planet/1> ;
    voc:releaseDate "1977-05-25"^^xsd:date .
    voc:starship <starship/12> .

Luke Skywalker’s voc:homeworld is the voc:Planet Tatooine, on which he was a voc:resident. He is also the voc:pilot of two voc:Starship‘s, namely the X-Wing and the Imperial Shuttle. He is also the voc:pilot of voc:Vehcile`s such as the Snowspeeder and Imperial Speeder Bike

The Star Wars RDF data which represents Luke Skywalker is fairly complex and it is therefore perhaps easier to understand the data and the relationships by referring to the following RDF instance diagram:

Luke Skywalker

Star Wars RDF – Model (Character, Film, Starship, Vehicle, Planet)

The following diagram depicts the Star Wars RDF model. RDF vocabularies (ontologies) provide the structure for RDF resources/instances such as Luke Skywalker or A New Hope

The model uses voc:Species, which are classes of individuals, but also have properties of their own (eg voc:averageLifespan). This means that Species is a meta-class, which may be a little hard to understand.

The Biological Taxonomy system (Species<Genus<Family<Order<Class<Phylum<Kingdom<Domain) is a well-known example of meta-classes. Each taxon has its own properties but also is a class of all the individuals in that taxon. Thus biological taxons deal with a 2-dimensional hierarchy.

Star Wars voc:Species are simpler. First, we declare it as a meta-class in RDF as follows:

voc:Species a rdfs:Class;
            rdfs:subClassOf rdfs:Class.

This shouldn’t be too surprising because rdfs:Class is, in fact, a meta-class itself:

rdfs:Class a rdfs:Class;
        rdfs:subClassOf rdfs:Class.

(Note: unlike the Metaobject protocol, RDFS collapses all meta-levels into one)

This allows a species such as voc:Human to both have individual properties (eg voc:averageLifespan), but also serve as the class of all humans (e.g., <human/1> Luke Skywalker):

@base <https://swapi.co/resource/> . 
@prefix voc: <https://swapi.co/vocabulary/> . 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

voc:Species a rdfs:Class ;
            rdfs:subClassOf rdfs:Class .

voc:Mammal a rdfs:Class .

voc:Sentient a rdfs:Class .
voc:Human a voc:Species ;
    rdfs:label "Human" ;
    rdfs:subClassOf voc:Mammal, voc:Sentient ;
    voc:averageLifespan 120.0 ;
    voc:film <film/1>, <film/2>...

<human/1> a voc:Human ; 
    rdfs:label "Luke Skywalker" ;
    voc:birthYear "19BBY" .

Visualizing Star Wars RDF Graphs

RDF is stored in GraphDB which allows one to navigate and traverse the Star Wars knowledge graph. Perhaps starting at Luke Skywalker by clicking on this GraphDb visualization.

Or perhaps you might want to visualize the voc:Droid species using this GraphDB Visualization link

This graph depicts that the voc:Characters that have a voc:Species of type voc:Droid appear in the voc:films A New Hope,The Empire Strikes Back, Return of the Jedi, The Phantom Menace, Attack of the Clones, Revenge of the Sith and The Force Awakens. Plus that there are six instances of type voc:DroidR4-P17, C-3PO, IG-88R2-D2, R5-D4, BB8.

Querying Star Wars RDF

Using the expressive power of the SPARQL query language it is possible to perform complex Star Wars data retrieval, aggregation and analytics tasks. The following simple queries barely scratch the surface of the power available. However, they are included so that you can get a sense of the query syntax and capabilities.

Return of the Jedi – Retrieve Luke Skywalker

Luke Skywalker data can be retrieved by running the following SPARQL CONSTRUCT query to retrieve an RDF representation. Please make use of the GraphDB Query Console to try it out.

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX voc: <https://swapi.co/vocabulary/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    ?lukeSkyWalker a ?type;
        rdfs:label ?label;
        voc:birthYear ?birthYear;
        voc:eyeColor ?eyeColor;
        voc:film ?film;
        voc:gender ?gender;
        voc:hairColor ?hairColor;
        voc:height ?height;
        voc:homeworld ?homeworld;
        voc:mass ?mass;
        voc:skinColor ?skinColor;
        voc:starship ?starship;
        voc:vehicle  ?vehicle.
    BIND (<https://swapi.co/resource/human/1> as ?lukeSkyWalker)
    ?lukeSkyWalker a ?type;
        rdfs:label ?label;
        voc:birthYear ?birthYear;
        voc:eyeColor ?eyeColor;
        voc:film ?film;
        voc:gender ?gender;
        voc:hairColor ?hairColor;
        voc:height ?height;
        voc:homeworld ?homeworld;
        voc:mass ?mass;
        voc:skinColor ?skinColor;
        voc:starship ?starship;
        voc:vehicle  ?vehicle.

Where are all the Droids? (Species subClass)

You may also, for example, want to retrieve the linked data for the species voc:Droid by invoking the following SPARQL CONSTRUCT query using the GraphDB Query Console:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
PREFIX voc: <https://swapi.co/vocabulary/> 
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    ?droidSpecies a ?type;
        rdfs:subClassOf ?subClassOf;
        rdfs:label ?label;
        voc:desc ?desc;
        voc:averageLifespan ?averageLifespan;
        voc:character ?character;
        voc:film ?film.
    BIND(voc:Droid as ?droidSpecies)
    ?droidSpecies a voc:Species;
                a  ?type;
                rdfs:subClassOf ?subClassOf ;
                rdfs:label ?label;
                voc:desc ?desc;
                voc:averageLifespan ?averageLifespan;
                voc:character ?character;
                voc:film ?film.

Rebel Assault (GraphQL and JSON)

So now that you have examined the RDF data and run some SPARQL queries across the data. Let’s take a look at the platforms Semantic Object service which has a GraphQL query and mutation endpoint.

You can start playing with the Star Wars GraphQL endpoint here.

Automagical GraphQL Schemas

The platforms Semantic Object service automagically generates a GraphQL schema that is aligned to the underlying RDF data. A simple declarative object mapping is configured and bound to the service using a YAML-based meta language. The Semantic Object Meta Language defines GraphQL shapes, restrictions, role-based access control and more… (More on the Semantic Object Meta Language in subsequent posts)

The generated Star Wars GraphQL schema, in this case, allows one to invoke filtered, ordered and pageable GraphQL queries for all of the RDF classes such as:

  • Films
  • Planets
  • Characters (All species, Human, Hutt, Droid, Kaleesh, etc..)
  • Starships
  • Vehicles

The Semantic Object Meta Language Schema model and it’s mapping to RDF can be explained by this object diagram:

SOML Diagram

Semantic Objects Meta Language Schema

For this blog post, we have limited the generated GraphQL schema, restricted to only include GraphQL queries, thus ensuring the Star Wars data is kept in a usable state!  GraphQL mutations can, of course, be turned on…. (more on mutations in a subsequent post!)

You can examine the generated Star Wars GraphQL schema within the “Docs” or “Documentation Explorer” tool within this GraphiQL instance.

Querying Star Wars JSON (GraphQL)

The following example Star Wars GraphQL queries and responses are included to indicate the types of queries that can be achieved using the Semantic Objects GraphQL endpoint.

A GraphiQL service is located here, where you can view the GraphQL schema and try out queries (using autocomplete). You could perhaps also use the GraphQL playground which is also very nice.

The GraphQL endpoint you may use for testing your own GraphQL queries is as follows: https://swapi-platform.ontotext.com/graphql

Simple Object Queries

Simple Object queries allow one to fetch objects and related scalar properties such as an object instance of type Human, Droid, Hutt, Film, Starship etc.

Planets within the Star Wars universe

The following GraphQL query retrieves all the planets within the Star Wars universe


query allPlanets { planet { name climate gravity terrain diameter population orbitalPeriod population rotationPeriod } }






All Star Wars Films

The following GraphQL query retrieves all the Films within the Star Wars saga


query allFilms { film { name releaseDate openingCrawl episodeId } }






Nested Object Queries

Nested Object queries allow one to fetch objects and related objects using an objects single value properties (one-to-one) or multi-valued properties (one-to-many) relationships which are defined within the GraphQL schema.

For example, you might want to retrieve all the voc:film for a particular voc:Human. Or perhaps get voc:species information for a particular character.

Nested queries retrieve data for a type along with data from nested or related types.

It is possible to also filter, order and paginate nested objects. However, query examples of this kind will be covered in later sections.

Luke Skywalker’s Home world

This GraphQL query filters all Human objects by using an ID filter, Luke Skywalkers ID. The query also retrieves Luke’s homeworld Tatooine by using the multi-value homeworld object property.


query lukesHomeWorld { human(ID: "https://swapi.co/resource/human/1") { id name mass birthYear hairColor homeworld { name climate gravity terrain diameter population orbitalPeriod population rotationPeriod } } }






Luke SkyWalker’s, Homeworld and the Planet’s residents

This GraphQL query traverses two nested object properties: the homeworld Planet for a particular Human (Luke), then the multi-valued resident for a Planet.


query lukesHomeWorldandResidents { human(ID: "https://swapi.co/resource/human/1") { id name mass birthYear hairColor homeworld { id name climate gravity terrain diameter population orbitalPeriod population rotationPeriod resident { name hairColor } } } }





Ordered Queries

GraphQL query results can be ordered by using an orderBy input argument within multi value object properties.

Order (ascending or descending) can be requested by specifying the ASC or DESC enumerated value.

Planets ordered in ascending planet name order

The following GraphQL query retrieves all Star wars universe planets and orders them in ascending name order:


query allPlanets { planet(orderBy: {name: ASC}) { name climate gravity terrain diameter population orbitalPeriod population rotationPeriod } }





Nested Object Ordering

Nested objects can also be ordered by using the orderBy argument.

Characters that appeared in the Star Wars film A New Hope in ascending name order, with films ordered by release date

Retrieve an ascending ordered list of characters that appeared in the film “A New Hope”. The films a character appeared in (one of which must be “A New Hope”) must be ordered in ascending release date order.


query characterWhichAppearedInNewHopeFilmsOrdered { character(orderBy: {name: ASC}, where: {film: {name: {EQ: "A New Hope"}}}) { name film(orderBy: {releaseDate: ASC}) { name releaseDate } } }





Characters that appeared in the Star Wars film A New Hope that also have blue eyes, in descending height order, with the characters films ordered by episodeId

Retrieve a descending height ordered list of characters that appeared in the film “A New Hope” and have “blue” eyes. The films a character appeared in (one of which must be “A New Hope”) must be ordered in ascending episodeId order.


query characterWhichAppearedInNewHopeFilmsOrdered { character(orderBy: {height: DESC}, where: {film: {name: {EQ: "A New Hope"}}, eyeColor: {EQ: "blue"}}) { name eyeColor film(orderBy: {episodeId: ASC}) { name episodeId } } }




Starships that appeared in the Star Wars film Return of the Jedi in descending Max Atmosphering Speed order

Retrieve an ascending MaxAtomosphering Speed ordered list of starships that appeared in the film “*.jedi” with the films the starship appeared in.


query starshipsInReturnOfTheJedi { starship(where: {film: {name: {IRE: "^.*jedi.*"}}}, orderBy: {maxAtmospheringSpeed: DESC}) { maxAtmospheringSpeed film { name } } }





Human Species average lifespan, and all human characters ordered by mass

Retrieve the average life span of the Human species, and all human characters ordered by mass.


query humanSpeciesOrderByMass { species(where: {name: {EQ: "Human"}}) { name averageLifespan character(orderBy: {mass: ASC}) { name mass } } }




Paginated Queries

The operator’s LIMIT and OFFSET are used to paginate query results.

LIMIT specifies the number of objects to retrieve per page OFFSET determines which page slice to retrieve.

The following are examples of different pagination queries.

Star Wars characters ordered by hairColor with a page size of 10, retrieving the 3rd page

Retrieve all Star Wars characters ordered by mass. Batch the characters into groups of 10 results, returning the third batch of results (pagination).


query charactersPaged { character(orderBy: {mass: ASC}, limit: 10, offset: 3) { rdfs_label { value } mass } }




Filtered Queries

One can use the where: argument within GraphQL queries to filter results based on object property values, including nested objects property values.

It is possible to combine GraphQL query filters within the same where: argument by using the default AND connective and explicit connectives such as ANDOREXISTS.

Films directed by a character named *Lucas*

Retrieve all Films where Mark Hamil as a Role and a Character


query filmsWhereMarkHamilHasARole { film(where: {AND: [{role: {person: {name: {IRE: "^.*Hamil.*"}}}}, {role: {}}, {role: {character: {}}}]}) { name role(where: {AND: [{person: {name: {IRE: "^.*Hamil.*"}}}, {person: {}}, {character: {}}]}) { person { name } } } }




Droids that have a height greater than 1.5 meters and a mass less than or equal to 96


query filteredDroids { droid(where: {height: {GT: 1.5}, mass: {LTE: 96}}) { name mass height } }




Droids that have either red eyes or contain PO in their name

Retrieve any Droid which has red eyes or contains “PO” within their name.


query filteredDroidsRedPO { droid(where: {OR: [{eyeColor: {EQ: "red"}}, {name: {IRE: "PO"}}]}) { name eyeColor } }





Planets that contain tatooi within their name, and also have residents containing Skywalker within their name


query tatooineSkyWalkers { planet(where: {AND: [{name: {IRE: "^.*tatooi.*"}}, {resident: {name: {IRE: "^.*Skywalker.*"}}}]}) { name resident(where: {name: {IRE: "^.*Skywalker.*"}}) { name } } }





May the force be with you

GraphQL is a very popular graph query language, well used, known and liked by developers. The Ontotext Platform uses GraphQL to lower the barrier of entry to knowledge graph data, whilst still providing the full expressivity and power of SPARQL.

The platform’s GraphQL features provide an auto-generated, controlled, high-performance API and lense across RDF data. With an exciting roadmap to follow:

  • Complex nested, filtered GraphQL mutations with closed-world shape validation
  • Role-based security: schema, provenance and object/property level constraints
  • GraphQL query aggregates
  • GraphQL query federation (Elastic and MongoDB)
  • Denial of Service protection: complexity limits, throttling, object/size, query caching

“Someday I will become the most powerful Jedi ever”. — Anakin Skywalker

Go to the Ontotext Platform for more information or talk directly to our experts!

Article's content

Head Of Architecture at Allen & Overy

Jem is an experienced software practitioner, architect, and director of development. He has proven himself as one of the best semantic technology solution architects previously working at the BBC and the FT. As Chief Solution Architect, he is helping Ontotext to deliver a comprehensive analytics and publishing platform.

Declarative Knowledge Graph APIs

Stop wasting time, manually building data access code. Let the Ontotext platform auto-generate a fast, flexible, and scalable GraphQL API over your RDF knowledge graph.

Star Wars: Knowledge Graph Federation

Read how you can use Ontotext Platform’s GraphQL federation capabilities to provide a unified interface for querying all of your data sources in context and allow clients to fetch data from any number of data sources simultaneously, without needing to know which data comes from which source.

Return of the Jedi: Ontotext Platform Metamorphosis

Read how we armed the Ontotext Platform with new tools to make navigating through the Star Wars knowledge graph data even easier

A New Hope: The Rise of the Knowledge Graph

Read about how Ontotext Platform utilizes its potential to lower the entry barrier to knowledge graph data in an exploration of the Star Wars universe.

Ontotext Platform: A Global View Across Knowledge Graphs and Content Annotations

Jem Rayfield provides insights into the Ontotext Platform and how GraphDB’s MongoDB connector unifies the platform’s knowledge graph and annotation RDF stores.

Ontotext Platform: Semantic Annotation Quality Assurance & Inter-Annotator Agreement

Jem Rayfield, Chief Solution Architect at Ontotext, provides technical insights into the Ontotext Platform and in particular the role of its Curation Tool.

Ontotext Platform: Knowledge Quality via Efficient Annotation at Scale

Jem Rayfield, Chief Solution Architect at Ontotext, provides technical insights into the Ontotext Platform and its design choices.