sparqlsubclassontologysuperclassrdflib

How to get the lowest subclass of an instances in an rdf graph?


Imagine a ontology with several classes and subclasses. Now i use another namespace to instantiate for example a MathTeacher. MathTheacher is a subclass of Teacher and Teacher a subclass of Job.

Now i can easily query for all subclasses of the instance. But how to only return the lowest: MathTeacher?

Here the Ontology:

@prefix EX: <https://www.example.com#> .
@prefix jobOnt: <https://www.jobOnt.com#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

jobOnt:Job a rdfs:Class .

jobOnt:Teacher a rdfs:Class ;
    rdfs:subClassOf jobOnt:Job .

jobOnt:MathTeacher a rdfs:Class ;
    rdfs:subClassOf jobOnt:Teacher .

jobOnt:CalculusTeacher a rdfs:Class ;
    rdfs:subClassOf jobOnt:MathTeacher .

jobOnt:OptimizationTeacher a rdfs:Class ;
    rdfs:subClassOf jobOnt:MathTeacher .

EX:Bob a jobOnt:MathTeacher .

Now i want to query for the Job type of Bob. The closest i get is:

    SELECT ?type
    WHERE {
    EX:Bob a ?type .
    ?type rdfs:subClassOf* jobOnt:Teacher . 
    }

This returns: https://www.jobOnt.com#Teacher and https://www.jobOnt.com#MathTeacher

But i only want to get Math Teacher because it is the lowest one in the class hirarch.


Solution

  • You need to extend your SPARQL query in order to exclude the types that have sub-types of their own:

    SELECT ?type WHERE {
        EX:Bob a ?type .
        ?type rdfs:subClassOf* jobOnt:Teacher . 
        FILTER NOT EXISTS {
            EX:Bob a ?subtype .
            ?subtype rdfs:subClassOf ?type .
            FILTER ( ?subtype != ?type )
        }
    }