Star Wars

../_images/star-wars-heading.png

All the Star Wars data you have ever wanted, accessible via Semantic Objects GraphQL queries and linked RDF data via GraphDB SPARQL queries. The Star Wars dataset includes:

  • Characters

  • Species (Amphibian, Artificial, Insectoid, Mammal, Reptile)

  • Films

  • Planets

  • Starships

  • Vehicles

  • People (Actors, Directors, etc)

  • Film Roles (Peoples, role within Starwar’s Films)

  • Film Releases

  • Awards

  • Awards Recognition

  • Locations (birthPlace, citizenship)

RDF Data

The Star Wars data which is publicly available at SWAPI has been transformed by Ontotext from a JSON dataset into an RDF dataset. The RDF data model re-factors the data model enhancing Species classification etc.

The RDF data is available for download starwars-data.ttl.

If you would like to install the data and access the data via GraphQL or SPARQL, please follow the Semantic Objects Quick Start guide.

RDF Data Model

The RDF instance diagram that follows depicts core Star Wars RDF data model elements, including voc:Character, voc:Film, voc:Planet, voc:Starship, voc:Species and voc:Vehicle.

This RDF snippet describes Luke Skywalker:

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
# ...
<human/1> a voc:Human, voc:Mammal, voc:Sentient, 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 is a voc:Human, which infers that he is also a voc:Mamamal and voc:Sentient with a Semantic Object Type Human.

The RDF includes links to the voc:films in which Luke Skywalker is a voc:character, namely:

A voc:Film is depicted within the RDF dataset as follows:

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
# ...

<film/1> a voc:Film ;
    rdfs:label "A New Hope" ;
    voc:character <human/1> ;
    voc:episodeId 4 ;
    voc:planet <planet/1> ;
    voc:releaseDate "1977-05-25"^^xsd:date .
    voc:starship <starship/12> .

The following data links voc:Film’s to voc:Characters and voc:Person entities to describe a persons role within a Star Wars film. For example, Luke Skywalker was played by Mark Hamil within the film A New Hope. The data set also includes the voc:Person`s `voc:birthPlace and voc:citizen`ship data, in this case `Mark Hamil was born in Oakland California and is a citizen of the United States

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix wds: <http://www.wikidata.org/entity/statement/> .
@prefix wd: <http://www.wikidata.org/entity/> .

# ...

wds:q17738-0457387C-0C3C-4565-8C8D-FA9CB1AC968D
  a                 voc:FilmRole ;
  voc:character     <human/1> ;
  voc:film          <film/1> ;
  voc:person        wd:Q210447 ;
  voc:role          "cast member" ;
  voc:wikidataLink  wds:q17738-0457387C-0C3C-4565-8C8D-FA9CB1AC968D

wd:Q210447  a       voc:Person ;
  rdfs:label       "Mark Hamill"@en  ;
  voc:birthDate     "1951-09-25"^^xsd:date ;
  voc:birthPlace    wd:Q17042 ;
  voc:citizenOf     wd:Q30 ;
  voc:desc          "American actor, producer, director, and writer"@en ;
  voc:gender        "male" ;
  voc:image         <http://commons.wikimedia.org/wiki/Special:FilePath/Mark%20Hamill%20%282017%29.jpg> ;
  voc:wikidataLink  wd:Q210447 .

 wd:Q30  a                 voc:Country ;
         rdfs:label        "United States"@en ;
         voc:country       wd:Q30 ;
         voc:wikidataLink  wd:Q30 .

 wd:Q17042  a                 voc:Location ;
            rdfs:label        "Oakland, California"@en ;
            voc:country       wd:Q30 ;
            voc:wikidataLink  wd:Q17042 .

The data also includes voc:Film voc:awards. For example Alex Guiness got the best supporting actor gong at the Oscars

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix wds: <http://www.wikidata.org/entity/statement/> .
@prefix wd: <http://www.wikidata.org/entity/> .

# ...

wds:Q103894-A96A66F4-0FC7-492D-91C8-B80670F6EE72
      a                 voc:AwardRecognition ;
      voc:award         wd:Q106291 ;
      voc:awardDate     "1977-01-01"^^xsd:date ;
      voc:awardStatus   "nominated" ;
      voc:film          <film/1> ;
      voc:forWork       "Star Wars"@en-GB  ;
      voc:person        wd:Q103894 ;
      voc:wikidataLink  wds:Q103894-A96A66F4-0FC7-492D-91C8-B80670F6EE72 .

 wd:Q103894  a             voc:Person ;
         rdfs:label        "Alec Guinness"@en ;
         voc:birthDate     "1914-04-02"^^xsd:date ;
         voc:birthPlace    wd:Q123634 ;
         voc:citizenOf     wd:Q145 ;
         voc:desc          "British actor (1914-2000)"@en ;
         voc:gender        "male" ;
         voc:image         <http://commons.wikimedia.org/wiki/Special:FilePath/Alec%20Guinness%206%20Allan%20Warren.jpg> ;
         voc:residentOf    wd:Q124230 ;
         voc:wikidataLink  wd:Q103894 .

 wd:Q123634  a             voc:Location ;
         rdfs:label        "Marylebone"@en ;
         voc:country       wd:Q145 ;
         voc:wikidataLink  wd:Q123634 .

 wd:Q145  a                voc:Country ;
         rdfs:label        "United Kingdon"@en ;
         voc:country       wd:Q145 ;
         voc:wikidataLink  wd:Q145 .

Luke Skywalker’s voc:homeworld is the voc:Planet Tatooine, on which he was a voc:resident.

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
# ...

<planet/1> a voc:Planet ;
    rdfs:label "Tatooine" ;
    voc:climate "arid" ;
    voc:diameter 10465 ;
    voc:film <film/1>,
        <film/3>,
        <film/6> ;
    voc:gravity "1 standard" ;
    voc:orbitalPeriod 304 ;
    voc:population 200000 ;
    voc:resident <human/1> ;
    voc:rotationPeriod 23 ;
    voc:surfaceWater 1 ;
    voc:terrain "desert" .

Luke Skywalker was the voc:pilot of two voc:Starships, namely:

A starship such as X-Wing is modeled in the RDF as follows:

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
# ...

<starship/12> a voc:Starship ;
    rdfs:label "X-wing" ;
    voc:cargoCapacity 110 ;
    voc:consumables "1 week" ;
    voc:costInCredits 149999 ;
    voc:crew 1 ;
    voc:film <film/1>,
        <film/2>,
        <film/3> ;
    voc:hyperdriveRating "1.0"^^xsd:float ;
    voc:length "12.5"^^xsd:float ;
    voc:manufacturer "Incom Corporation" ;
    voc:maxAtmospheringSpeed 1050 ;
    voc:mglt 100 ;
    voc:model "T-65 X-wing" ;
    voc:passengers 0 ;
    voc:pilot <human/1> ;
    voc:starshipClass "Starfighter" .

Luke Skywalker is also the voc:pilot of voc:Vehicles such as:

A voc:Vehicle such as the Snowspeeder is depicted within the RDF as:

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .
# ...

<vehicle/14> a voc:Vehicle ;
    rdfs:label "Snowspeeder" ;
    voc:cargoCapacity 10 ;
    voc:consumables "none" ;
    voc:crew 2 ;
    voc:film <film/2> ;
    voc:length "4.5"^^xsd:float ;
    voc:manufacturer "Incom corporation" ;
    voc:maxAtmospheringSpeed 650 ;
    voc:model "t-47 airspeeder" ;
    voc:passengers 0 ;
    voc:pilot <human/1> ;
    voc:vehicleClass "airspeeder" .

This RDF instance diagram intends to capture the RDF described above.

../_images/star-wars-luke-skywalker.png

Once the Star Wars data is loaded within GraphDB following the Semantic Objects Quick Start guide, it is possible to navigate through the RDF data to visualize Luke Skywalker by clicking on this GraphDB visualization link.

The GraphDB visualization for Luke Skywalker is as follows:

../_images/graphdb-visual-luke-skywalker.png

Luke Skywalker RDF data can also be retrieved by querying GraphDB by invoking the following SPARQL CONSTRUCT query using the GraphDB Query Console:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX so: <http://www.ontotext.com/semantic-object/>
PREFIX voc: <https://swapi.co/vocabulary/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
CONSTRUCT {
    ?lukeSkyWalker a ?type;
        rdfs:label ?label;
        voc:birthYear ?birthYear;
        voc:eyeColor ?eyeColo;
        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 {
    BIND (<https://swapi.co/resource/human/1> as ?lukeSkyWalker)
    ?lukeSkyWalker a ?type;
        rdfs:label ?label;
        voc:birthYear ?birthYear;
        voc:eyeColor ?eyeColo;
        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.
}

Class (Character, Film, Starship, Vehicle, Planet)

The following diagram depicts the Star Wars RDF class model:

../_images/star-wars-class.png

SWAPI uses Species, which are classes of individuals, but also have properties of their own (e.g., 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.

The SWAPI Species is simpler. First, we declare it as a meta-class in RDF as follows:

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

This should not 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 Human to both have individual properties (e.g., averageLifespan), but also serve as the class of all humans (e.g., <human/1> Luke Skywalker):

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: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" .

The following diagrams depict the groups of Star Wars species meta-classes:

Amphibian Species

../_images/star-wars-amphibian-species.png

Artificial Species

../_images/star-wars-artifical-species.png

Insectoid Species

../_images/star-wars-insectoid-species.png

Mammal Species

../_images/star-wars-mamal-species.png

Reptile Species

../_images/star-wars-reptile-species.png

Droid (subClassOf Artificial Species)

../_images/droids-smaller-height.jpg

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

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX so: <http://www.ontotext.com/semantic-object/>
PREFIX voc: <https://swapi.co/vocabulary/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
CONSTRUCT {
    ?droidSpecies a ?type;
        rdfs:subClassOf ?subClassOf;
        rdfs:label ?label;
        voc:desc ?desc;
        voc:averageLifespan ?averageLifespan;
        voc:character ?character;
        voc:film ?film.
} WHERE {
    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.
}

Returning the following RDF:

@base <https://swapi.co/resource/> .
@prefix so: <http://www.ontotext.com/semantic-object/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

voc:Droid a rdfs:Class, voc:Species;
    rdfs:label "Droid";
    rdfs:subClassOf voc:Artificial, voc:Sentient;
    voc:averageLifespan "indefinite";
    voc:character <droid/2>,
        <droid/23>,
        <droid/3>,
        <droid/8>,
        <droid/87>;
    voc:desc "A droid is a fictional robot possessing some degree of artificial intelligence in the Star Wars science fiction franchise. Coined by special effects artist John Stears, the term is a clipped form of \"android\",1 a word originally reserved for robots designed to look and act like a human.2 The word \"droid\" has been a registered trademark of Lucasfilm Ltd since 1977.3456";
    voc:film <film/1>,
        <film/2>,
        <film/3>,
        <film/4>,
        <film/5>,
        <film/6>,
        <film/7> .

Or perhaps visualize the voc:Droid species within the GraphDB Visualizer:

../_images/graphdb-visual-droid.png

Depicting that voc:Droid appears in voc:film:

And there are six instances of type voc:Droid:

Semantic Objects Modeling Language

Semantic Objects generates a GraphQL schema by using a Semantic Objects Modeling Language (SOML) schema.

This section of the document describes how the Star Wars RDF is mapped to Semantic Objects.

Schema

The Star Wars RDF data is mapped to Semantic Objects using the Semantic Object Modeling Language (SOML).

You can download the Semantic Object schema.yaml .

Prefixes

The Star Wars RDF uses a set of namespace prefix bindings. Namespace prefix bindings are used as an abbreviation that is attached as a local name.

@prefix so: <http://www.ontotext.com/semantic-object/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

These prefix bindings are re-used and represented within the Star Wars SOML definition. In addition to Star Wars schema-specific namespaces and well-known system namespaces, the so: namespace is used for holding built-in props like:

  • so:name: the semantic object name

The Star Wars prefixes are defined as:

prefixes:
    # common prefixes
    so: "http://www.ontotext.com/semantic-object/"
    voc: "https://swapi.co/vocabulary/"
    dct: "http://purl.org/dc/terms/"
    gn: "http://www.geonames.org/ontology#"
    owl: "http://www.w3.org/2002/07/owl#"
    puml: "http://plantuml.com/ontology#"
    rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    rdfs: "http://www.w3.org/2000/01/rdf-schema#"
    skos: "http://www.w3.org/2004/02/skos/core#"
    void: "http://rdfs.org/ns/void#"
    wgs84: "http://www.w3.org/2003/01/geo/wgs84_pos#"
    xsd: "http://www.w3.org/2001/XMLSchema#"
    wds: "http://www.wikidata.org/entity/statement/" .
    wd: "http://www.wikidata.org/entity/" .

specialPrefixes:
    base_iri:          https://swapi.co/resource/
    vocab_iri:         https://swapi.co/vocabulary/
    vocab_prefix:      voc

The base_iri maps directly to base and allows relative IRIs from the base. In the case of Star Wars:

@base <https://swapi.co/resource/> .
@prefix voc: <https://swapi.co/vocabulary/> .

<#vehicle/14> a voc:Vehicle .

Expands to:

<https://swapi.co/resource/vehicle/14> a <https://swapi.co/vocabulary/Vehicle>

The vocab_iri is the default namespace prefix binding for RDF ontology elements within the RDF data.

In the case of Star Wars:

vocab_iri:         https://swapi.co/vocabulary/
vocab_prefix:      voc

Can be directly mapped to the RDF Star Wars ontology elements such as voc:Droid or voc:averageLifespan:

@prefix so: <http://www.ontotext.com/semantic-object/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix voc: <https://swapi.co/vocabulary/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# Droid Species Class
voc:Droid a rdfs:Class, voc:Species;
    rdfs:subClassOf voc:Artificial, voc:Sentient .

voc:averageLifespan a owl:DatatypeProperty ;
    rdfs:domain voc:Planet ;
    rdfs:range xsd:string .

The Star Wars SOML definition does not need to declare the default vocab_prefix within the YAML for this mapping.

For example:

objects:
    Species:
        ....
        props:
        ...
        averageLifespan: {descr: "Lifespan of the species", range: decimal}
        ...

And allows the Semantic Objects Service to produce an RDF mapping as follows:

  • Species: == rdf:type is voc:Species

  • averageLifespan == voc:averageLifespan

It is of course possible to define the prefix within SOML YAML if you want to, so that it is explicit. Thus, the following is a more verbose but equivalent definition:

objects:
    Species:
        #....
        type: ["voc:Species"]
        props:
            #...
            voc:averageLifespan: {descr: "Lifespan of the species", range: decimal}
            #...

Semantic Objects

The Star Wars SOML schema defines the following Semantic Objects where the Semantic Object types are mapped to RDF:

  • Species: object representing meta information about a species such as a Droids voc:averageLifespan etc.

    • a voc:Species

  • Film: object representing one of the Start Wars films

    • a voc:Film

  • Planet: object representing one of the Star Wars Planets

    • a voc:Planet

  • Vehicle: object representing one of the Star Wars Vehicles

    • a voc:Vehicle

  • Starship: object representing one of the Star Wars Spacecraft

    • a voc:Starship

  • Character (Abstract): an abstract object type for representing all character individuals such as Luke Skywalker or R2-D2

    • a voc:Character

  • Character sub-types: concrete sub-types for representing individuals that have species type (see species), e.g., Aleena, Besalisk, Cerean, Chagrian, Clawdite, Droid, etc…) inherits character properties

    • voc:Aleena....voc:Droid…etc.

  • FilmRole: a persons roles within a Starwars film. E.g. Mark Hamil was the actor for the character Luke Skywalker in the film A New Hope

  • Person: people related to Starwars for example Mark Hamil the american actor

  • Location: location data for birthPlace and country of citzenship

  • Award: data such as academy awards

Example: Film Object

The following Semantic Object definition is included as an example. This YAML defines the Film: Semantic Object and how it maps to RDF.

Film:
  descr: 'Star Wars is an American epic space-opera media franchise created by George Lucas. The franchise began with the eponymous 1977 film and quickly became a worldwide pop-culture phenomenon, with many more films'
  inherits: HasWikidataLink
  type: voc:Film
  label: Film
  name: rdfs:label
  props:
    boxOffice: {}
    character: {}
    cost: {}
    desc: {}
    episodeId: {}
    image: {}
    location: {}
    openingCrawl: {}
    planet: {}
    rdfs:label:
     min: 1
    releaseDate: {}
    returnOnInvestment: {}
    starship: {}
    vehicle: {}
    awardRecognition: {descr: "Awards of the film", max: inf, range: AwardRecognition, inverseAlias: film, rangeCheck: true}
    release: {descr: "Releases of the film", max: inf, range: FilmRelease, inverseAlias: film, rangeCheck: true}
    role: {descr: "Roles associated with the film", max: inf, range: FilmRole, inverseAlias: film, rangeCheck: true}

Which has a direct mapping to an voc:Film instance representing A New Hope as follows:

<film/1> a voc:Film ;
    rdfs:label "A New Hope"^^xsd:string ;
    voc:character <droid/2>,
         # --- more ---
        <wookiee/13> ;
    voc:desc "\"Star Wars (later retitled Star Wars: Episode IV – A New Hope) is a 1977 American epic space opera film written and directed by George Lucas. It is the first film in the original Star Wars trilogy, the first Star Wars movie in general, and the beginning of the Star Wars franchise. Starring Mark Hamill, Harrison Ford, Carrie Fisher, Peter Cushing, Alec Guinness, David Prowse, James Earl Jones, Anthony Daniels, Kenny Baker, and Peter Mayhew, the films plot focuses on the Rebel Alliance, led by Princess Leia (Fisher), and its attempt to destroy the Galactic Empires space station, the Death Star. This conflict disrupts the isolated life of farmhand Luke Skywalker (Hamill), who inadvertently acquires a pair of droids that possess stolen architectural plans for the Death Star. When the Empire begins a destructive search for the missing droids, Skywalker accompanies Jedi Master Obi-Wan Kenobi (Guinness) on a mission to return the plans to the Rebel Alliance and rescue Leia from her imprisonment by the Empire.\", Star Wars was released in theatres in the United States on May 25, 1977. It earned $461 million in the U.S. and $314 million overseas, totaling $775 million ($3.132 billion in 2017 dollars, adjusted for inflation). It surpassed Jaws (1975) to become the highest-grossing film of all time until the release of E.T. the Extra-Terrestrial (1982). When adjusted for inflation, Star Wars is the second-highest-grossing film in North America, and the third-highest-grossing film in the world. It received ten Academy Award nominations (including Best Picture), winning seven. It was among the first films to be selected as part of the U.S. Library of Congress\\ National Film Registry as being \"culturally, historically, or aesthetically significant\". At the time, it was the most recent film on the registry and the only one chosen from the 1970s. Its soundtrack was added to the U.S. National Recording Registry in 2004. Today, it is often regarded as one of the most important films in the history of motion pictures. It launched an industry of tie-in products, including TV series spinoffs, novels, comic books, and video games, and merchandise including toys, games and clothing., \"The films success led to two critically and commercially successful sequels, The Empire Strikes Back in 1980 and Return of the Jedi in 1983. Star Wars was reissued multiple times at Lucas behest, incorporating many changes including modified computer-generated effects, altered dialogue, re-edited shots, remixed soundtracks, and added scenes. A prequel trilogy was released beginning with The Phantom Menace in 1999, continuing with Attack of the Clones in 2002, and concluding with Revenge of the Sith in 2005. The film was followed by a sequel trilogy beginning with The Force Awakens in 2015. A direct prequel, Rogue One, was released in 2016. The films fourth sequel, The Last Jedi, will be released in December 2017.\""^^xsd:string ;
    voc:episodeId 4 ;
    voc:openingCrawl """It is a period of civil war.\r
                    Rebel spaceships, striking\r
                    -- more --
                    freedom to the galaxy...."""^^xsd:string ;
    voc:planet <planet/1>, <planet/2>, <planet/3> ;
    voc:releaseDate "1977-05-25"^^xsd:date ;
    voc:starship <starship/10>,
        # --- more ---
        <starship/9> ;
    voc:vehicle <vehicle/4>,
        # --- more ---
        <vehicle/8> .

Species

In SOML, we declare the properties of a species (e.g., Human:) and how these map to individual characters (e.g., <human/1>).

We also declare links between the instances:

  • Character->species->Species (being rdf:type) to get the single species of a character. rdfProp uses the voc:Character rdf:type for the species relationship. It uses rangeCheck: true to ensure that the chosen type is a voc:Species.

  • Species->character->Character (inverseAlias of the above) to get the list of characters for a species

objects:
  Species:
    props:
      averageLifespan: {descr: "Lifespan of the species", range: decimal}
      film: {descr: "Films the species appears in", max: inf, range: Film}
      character: {descr: "List of instances of the species", max: inf, range: Character, inverseAlias: "species", rangeCheck: true}

  Character:
    kind: abstract
    props:
      birthYear: {descr: "In BBY (Before the Battle of Yalvin) or ABY (After the battle of Yalvin"}
      species: {label: "Characters species", range: Species, rdfProp: "rdf:type", rangeCheck: true, min: 1}

Within the RDF Human is a subclass of other species (Mammal and Sentient), however within the SOML definition we declare that Human: inherits the properties of Character:.

Human:
  inherits: Character
  prefix: "human/"
  descr: "Modern humans (Homo sapiens..."

This allows one to access all characters by its Species type, plus access their Character: properties.

The SOML schema makes use of inheritance to reduce the need of repeating Character properties for all the sub-objects such as Human: or Droid:, e.g.:

Character:
    kind: abstract
     props:
        # --- more ---
        birthYear: {descr: "In BBY (Before the Battle of Yalvin) or ABY (After the battle of Yalvin"}
        species: {label: "Characters species", range: Species, rdfProp: "rdf:type", rangeCheck: true, min: 1}
        # --- more ---

Human:
    inherits: Character

# --- more ---

Droid:
    inherits: Character

The full set of Semantic Object species that inherit property characteristics from Character is as follows:

Aleena, Besalisk, Cerean, Chagrian, Clawdite, Droid, Dug, Ewok, Geonosian, Gungan, Human, Hutt, Iktotchi, Kaleesh, Kaminoan, Keldor, Mirialan, Moncalamari, Muun, Nautolan, Neimodian, Pauan, Quermian, Rodian, Skakoan, Sullustan, Tholothian, Togruta, Toong, Toydarian, Trandoshan, Twilek, Umbaran, Vulptereen, Wookiee, Xexto, Yodasspecies, Zabrak.

Elasticsearch Indices

The following classes have been marked as searchable in the SOML schema:

  • Human

  • Character

  • Wookiee

  • Droid

  • Film

  • Planet

  • Starship

  • Vehicle

  • Person

And the following class properties have been marked as searchable:

  • Award

  • AwardRecognition

  • FilmRole

  • FilmRelease

  • Location

  • Country

Find more information on how to mark objects and properties as searchable in the Search Configuration.

Generated GraphQL Schema

The Semantic Objects Service generates a GraphQL schema that is exposed at the /graphql endpoint.

Note

The GraphQL endpoint should only be used from a compatible GraphQL client such as GraphiQL.

The generated GraphQL schema currently only includes GraphQL queries and does not include any mutation definitions.

The GraphQL schema provides a query schema providing access across all of the Semantic Object, Semantic Object Properties, and Relationships.

The Semantic Objects Service transforms the SOML YAML into GraphQL schema definitions automatically when the SOML schema is bound to the service.

The GraphQL schema cannot be altered directly. It must be generated by using a Semantic Objects Modeling Language schema. This ensures that a correct GraphQL->SPARQL->RDF mapping is in place.

The GraphQL schema aligns with the Semantic Object RDF mapping, allowing the Semantic Object transpiler to transform GraphQL into SPARQL to retrieve the underlying RDF data.

Get the Schema

You can download the Semantic Objects generated GraphQL Schema using the following instructions.

  1. Set up the Platform following the Semantic Objects Quick Start guide.

  2. Install npm.

  3. Install get-graphql-schema:

npm install -g get-graphql-schema
  1. Download the GraphQL schema:

get-graphql-schema https://swapi-platform.ontotext.com/graphql > ${path}

GraphQL Object Types

The Semantic Objects Service generates GraphQL Object Types for each Semantic Object defined with the SOML YAML.

As an example, the Film: Semantic Objects Modeling Language definition:

Film:
  descr: 'Star Wars is an American epic space-opera media franchise created by George Lucas. The franchise began with the eponymous 1977 film and quickly became a worldwide pop-culture phenomenon, with many more films'
  inherits: HasWikidataLink
  type: voc:Film
  label: Film
  name: rdfs:label
  props:
    boxOffice: {}
    character: {}
    cost: {}
    desc: {}
    episodeId: {}
    image: {}
    location: {}
    openingCrawl: {}
    planet: {}
    rdfs:label:
     min: 1
    releaseDate: {}
    returnOnInvestment: {}
    starship: {}
    vehicle: {}
    awardRecognition: {descr: "Awards of the film", max: inf, range: AwardRecognition, inverseAlias: film, rangeCheck: true}
    release: {descr: "Releases of the film", max: inf, range: FilmRelease, inverseAlias: film, rangeCheck: true}
    role: {descr: "Roles associated with the film", max: inf, range: FilmRole, inverseAlias: film, rangeCheck: true}

is transformed into a GraphQL Object type as follows:

# Film
type Film implements Object & Nameable & HasWikidataLink {
  # IRI
  id: ID

  # type
  type(ID: [ID!], orderBy: _OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: ID_Where_Multi): [ID]!

  # Name
  name(lang: String = "ANY"): String

  # wikidata link
  wikidataLink: ID

  # box office
  boxOffice: Decimal

  # character
  character(lang: String, ID: [ID!], orderBy: Character_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: Character_Where_Multi): [Character]!

  # cost
  cost: Decimal

  # Description
  desc(value: String_Where, lang: String): Literal

  # episode id
  episodeId: Integer

  # image
  image(ID: [ID!], orderBy: _OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: ID_Where_Multi): [ID]!

  # Location
  location(lang: String, ID: [ID!], orderBy: Location_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: Location_Where_Multi): [Location]!

  # openingCrawl
  openingCrawl: String

  # planet
  planet(lang: String, ID: [ID!], orderBy: Planet_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: Planet_Where_Multi): [Planet]!

  # name
  rdfs_label(value: String_Where, lang: String): Literal

  # Date
  releaseDate: Date

  # return on investment
  returnOnInvestment: Decimal

  # Starships in film or piloted by character
  starship(lang: String, ID: [ID!], orderBy: Starship_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: Starship_Where_Multi): [Starship]!

  # vehicle
  vehicle(lang: String, ID: [ID!], orderBy: Vehicle_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: Vehicle_Where_Multi): [Vehicle]!

  # awardRecognition
  awardRecognition(lang: String, ID: [ID!], orderBy: AwardRecognition_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: AwardRecognition_Where_Multi): [AwardRecognition]!

  # release
  release(lang: String, ID: [ID!], orderBy: FilmRelease_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: FilmRelease_Where_Multi): [FilmRelease]!

  # role
  role(lang: String, ID: [ID!], orderBy: FilmRole_OrderBy, limit: PositiveInteger, offset: PositiveInteger, where: FilmRole_Where_Multi): [FilmRole]!
}

You will notice that multi-valued Object properties are always adorned with the following input arguments:

  • ID: a filter that ensures that only those IDs stated are retrieved

  • limit: a pagination filter that limits the number of values retrieved within a page

  • offset: a pagination filter that specifies the number of pages which you wish to skip before retrieving the objects

  • orderBy: object property ordering, supporting order by object and nested object properties (See GraphQL Order Objects)

  • where: object property filter (object and nested object properties) (See GraphQL Where Objects)

GraphQL Order Objects

Multi-valued object properties such as a Films characters:

type Film implements Nameable & Object {
    character(ID: [ID!],
             limit: PositiveInteger,
             offset: PositiveInteger,
             orderBy: Character_OrderBy,
             where: Character_Where_Multi): [Character]!
}

Always include an orderBy: input argument. This argument uses a generated {Type}_OrderBy type, e.g.:

orderBy: Character_OrderBy,

The generated {Type}_OrderBy input objects are defined so that it is possible to retrieve an ordered set of objects by any of the objects properties.

In this particular case, Film.character ordering has a Character_OrderBy input object as follows:

enum _OrderBy {
    ASC
    DESC
}

input Character_OrderBy {
    __typename: _OrderBy
    birthYear: _OrderBy
    desc: _OrderBy
    eyeColor: _OrderBy
    gender: _OrderBy
    hairColor: _OrderBy
    height: _OrderBy
    homeworld: Planet_OrderBy
    id: _OrderBy
    mass: _OrderBy
    name: _OrderBy
    skinColor: _OrderBy
}

Every multi-valued object property has its own {Type}_OrderBy input object. As you can see in the example above, e.g.:

input Character_OrderBy {
    homeworld: Planet_OrderBy
}

The {Type}_OrderBy input objects support orderBy queries (see GraphQL Query Ordering), such as:

  • “Retrieve the list of characters that appeared in the Star Wars film “A New Hope” in descending height order”

  • “Retrieve the list of starships which appeared in the Star Wars film “Return of the Jedi” in ascending length order”

  • etc..

GraphQL Where Objects

Multi-valued object properties such as a Films and starships use a generated {Type}_Where_Multi input argument for multi-valued object filtering. For example:

type Film implements Nameable & Object {
    # ....
    starship(ID: [ID!],
            limit: PositiveInteger,
            offset: PositiveInteger,
            orderBy: Starship_OrderBy,
            where: Starship_Where_Multi): [Starship]!
}

This generated argument type {Type}_Where_Multi allows a GraphQL query to build a filter using connectives such as AND, ALL, OR, ALL_EXISTS with object property comparisons using generated input objects {Type}_Where, which include comparisons such as EQ (Equal), NEQ (Not Equal), IRE (Case-insensitive Regular Expression), etc.

For example:

input Starship_Where_Multi {

    # ForAll for Starship
    ALL: Starship_Where_Multi

    # All and Exists for Starship
    ALL_EXISTS: Starship_Where_Multi

    # Conjunction of Starship comparisons
    AND: [Starship_Where_Multi!]

    # Check by id
    ID: [ID!]

    # Negation of Starship comparisons
    NOT: Starship_Where_Multi

    # Disjunction of Starship comparisons
    OR: [Starship_Where_Multi!]

    # cargoCapacity comparisons
    cargoCapacity: Integer_Where

    # consumables comparisons
    consumables: String_Where

    # costInCredits comparisons
    costInCredits: Integer_Where

    # crew comparisons
    crew: Integer_Where

    # desc comparisons
    desc: String_Where

    # film comparisons
    film: Film_Where_Multi

    # hyperdriveRating comparisons
    hyperdriveRating: Decimal_Where

    # id comparisons
    id: ID_Where

    # length comparisons
    length: Decimal_Where

    # manufacturer comparisons
    manufacturer: String_Where

    # maxAtmospheringSpeed comparisons
    maxAtmospheringSpeed: Integer_Where

    # mglt comparisons
    mglt: Integer_Where

    # model comparisons
    model: String_Where

    # name comparisons
    name: String_Where

    # passengers comparisons
    passengers: Integer_Where

    # pilot comparisons
    pilot: Character_Where_Multi

    # starshipClass comparisons
    starshipClass: String_Where

    # type comparisons
    type: ID_Where_Multi

}

# String comparisons for single-value fields
input String_Where {

    # Conjunction of String comparisons
    AND: [String_Where!]

    # Equal to String
    EQ: String

    #Greater than String
    GT: String

    #Greater than or equal to String
    GTE: String

    #In list of String
    IN: [String!]

    # Case-insensitive regex match
    IRE: String

    # Less than String
    LT: String

    # Less than or equal to String
    LTE: String

    # Not equal to String
    NEQ: String

    # Not in list of String
    NIN: [String!]

    # Case-insensitive regex mismatch
    NIRE: String

    # Regex mismatch
    NRE: String

    # Disjunction of String comparisons
    OR: [String_Where!]

    # Regex match
    RE: String
}

The {Type}_Where_Multi and {Type}_Where input objects support orderBy queries (see GraphQL Query Ordering), such as:

  • “Retrieve starships that have at least one tall pilot ordered”

  • “Retrieve starships which have a particular cargo capacity”

  • “Retrieve planets where resident name includes “SkyWalker””

  • “Retrieve humans where there homeworld name include “Tato””

  • etc..

GraphQL Query Types

The Semantic Objects service automatically generates queries within the GraphQL schema for all Semantic Objects.

The acceptable queries defined within the GraphQL schema have the same input arguments described in the above sections, namely:

  • ID: a filter that ensures that only those IDs stated are retrieved

  • limit: a pagination filter that limits the number of values retrieved within a page

  • offset: a pagination filter that specifies the number of pages which you wish to skip before retrieving the objects

  • orderBy: object property ordering, supporting order by object and nested object properties (See GraphQL Order Objects)

  • where: object property filter, by object and nested object properties (See GraphQL Where Objects)

The Star Wars GraphQL schema therefore allows one to invoke filters, ordered and pageable GraphQL queries for:

  • Films

  • Planets

  • Characters (All species)

  • Starships

  • Vehicles

type Query {
    aleena(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Aleena_OrderBy, where: Aleena_Where_Multi): [Aleena]!
    besalisk(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Besalisk_OrderBy, where: Besalisk_Where_Multi): [Besalisk]!
    cerean(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Cerean_OrderBy, where: Cerean_Where_Multi): [Cerean]!
    chagrian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Chagrian_OrderBy, where: Chagrian_Where_Multi): [Chagrian]!
    character(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Character_OrderBy, where: Character_Where_Multi): [Character]!
    clawdite(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Clawdite_OrderBy, where: Clawdite_Where_Multi): [Clawdite]!
    droid(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Droid_OrderBy, where: Droid_Where_Multi): [Droid]!
    dug(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Dug_OrderBy, where: Dug_Where_Multi): [Dug]!
    ewok(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Ewok_OrderBy, where: Ewok_Where_Multi): [Ewok]!
    film(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Film_OrderBy, where: Film_Where_Multi): [Film]!
    geonosian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Geonosian_OrderBy, where: Geonosian_Where_Multi): [Geonosian]!
    gungan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Gungan_OrderBy, where: Gungan_Where_Multi): [Gungan]!
    human(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Human_OrderBy, where: Human_Where_Multi): [Human]!
    hutt(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Hutt_OrderBy, where: Hutt_Where_Multi): [Hutt]!
    iktotchi(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Iktotchi_OrderBy, where: Iktotchi_Where_Multi): [Iktotchi]!
    kaleesh(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Kaleesh_OrderBy, where: Kaleesh_Where_Multi): [Kaleesh]!
    kaminoan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Kaminoan_OrderBy, where: Kaminoan_Where_Multi): [Kaminoan]!
    keldor(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Keldor_OrderBy, where: Keldor_Where_Multi): [Keldor]!
    mirialan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Mirialan_OrderBy, where: Mirialan_Where_Multi): [Mirialan]!
    moncalamari(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Moncalamari_OrderBy, where: Moncalamari_Where_Multi): [Moncalamari]!
    muun(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Muun_OrderBy, where: Muun_Where_Multi): [Muun]!
    nautolan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Nautolan_OrderBy, where: Nautolan_Where_Multi): [Nautolan]!
    neimodian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Neimodian_OrderBy, where: Neimodian_Where_Multi): [Neimodian]!
    object(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Object_OrderBy, where: Object_Where_Multi): [Object]!
    pauan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Pauan_OrderBy, where: Pauan_Where_Multi): [Pauan]!
    planet(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Planet_OrderBy, where: Planet_Where_Multi): [Planet]!
    quermian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Quermian_OrderBy, where: Quermian_Where_Multi): [Quermian]!
    rodian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Rodian_OrderBy, where: Rodian_Where_Multi): [Rodian]!
    skakoan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Skakoan_OrderBy, where: Skakoan_Where_Multi): [Skakoan]!
    species(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Species_OrderBy, where: Species_Where_Multi): [Species]!
    starship(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Starship_OrderBy, where: Starship_Where_Multi): [Starship]!
    sullustan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Sullustan_OrderBy, where: Sullustan_Where_Multi): [Sullustan]!
    tholothian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Tholothian_OrderBy, where: Tholothian_Where_Multi): [Tholothian]!
    togruta(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Togruta_OrderBy, where: Togruta_Where_Multi): [Togruta]!
    toong(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Toong_OrderBy, where: Toong_Where_Multi): [Toong]!
    toydarian(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Toydarian_OrderBy, where: Toydarian_Where_Multi): [Toydarian]!
    trandoshan(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Trandoshan_OrderBy, where: Trandoshan_Where_Multi): [Trandoshan]!
    twilek(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Twilek_OrderBy, where: Twilek_Where_Multi): [Twilek]!
    umbaran(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Umbaran_OrderBy, where: Umbaran_Where_Multi): [Umbaran]!
    vehicle(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Vehicle_OrderBy, where: Vehicle_Where_Multi): [Vehicle]!
    vulptereen(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Vulptereen_OrderBy, where: Vulptereen_Where_Multi): [Vulptereen]!
    wookiee(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Wookiee_OrderBy, where: Wookiee_Where_Multi): [Wookiee]!
    xexto(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Xexto_OrderBy, where: Xexto_Where_Multi): [Xexto]!
    yodasspecies(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Yodasspecies_OrderBy, where: Yodasspecies_Where_Multi): [Yodasspecies]!
    zabrak(ID: [ID!], limit: PositiveInteger, offset: PositiveInteger, orderBy: Zabrak_OrderBy, where: Zabrak_Where_Multi): [Zabrak]!
}

GraphQL Queries

GraphQL queries examples for the Star Wars dataset can be found in the GraphQL Query Tutorial sections: