Search code examples
sparqlsemantic-web

SPARQL: Get "most specific property"


I'm trying to fetch the most specific properties for a class, and I'm stuck. I want to pull out all the properties that apply for a given class (including those inherited from superclasses), except those properties that have subproperties in the result set.

For example, if I have a class Population with one of its properties being atLocation, and a subclass of Population called Refugees. Refugees has a property currentLocation, which is a subProperty of atLocation.

So what I want is a generic query that would give me only atLocation if I put in Population, and only currentLocation if I put in Refugees. What I have is this:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
prefix ex: <http://example.org/vocabulary#>

SELECT DISTINCT ?prop WHERE {
  ex:Refugee rdfs:subClassOf* ?domain  .
  ?prop rdfs:domain ?domain .
  ?subprop rdfs:domain ?domain .
  FILTER NOT EXISTS { ?subprop rdfs:subPropertyOf ?prop . }  
} ORDER BY ?prop

This gives me both atLocation and currentLocation, though.

Is this possible in one query at all? Any ideas on how to solve this appreciated!


Solution

  • This was trickier than I anticipated when I tried it for myself. However, what you need to do is extend your NOT EXISTS clause somewhat.

    SELECT ?prop WHERE {
      ?prop rdfs:domain ?domain .
      ?class rdfs:subClassOf* ?domain .
      FILTER NOT EXISTS {
            ?sub rdfs:subPropertyOf ?prop.
            ?sub rdfs:domain ?d.
            ?class rdfs:subClassOf* ?d .
      }
      FILTER (?class = ex:Refugee)
    }
    

    We're selecting all properties whose domain is ex:Refugee or a superclass of ex:Refugee (first two BGPs). But then we want to filter out those properties for which a subProperty exists that also has a domain which is (a superclass of) ex:Refugee. Note that we are using a different variable for the domain of the sub-property (?d), after all it does not necessarily have to have the exact same domain as the property we are selecting.

    The above works on a simple (non-entailment or RDF(S) entailment) triplestore, provided each sub-property only has its most specific domain class defined, that is, you have the triple 'ex:currentLocation rdfs:domain ex:Refugee' but not explicitly 'ex:currentLocation rdfs:domain ex:Population'.