Aidos
Aidos

Reputation: 769

SPARQL query for retrieving individuals

Please help me with the SPARQL query. I have an ontology with the class 'Building' as a subclass of owl:Thing. 'Building' has it's own sub classes like: Church, Medical, Shop. Each of these sub classes has it's own labels ( seeAlso ). For instance: Shop has labels like supermarket, bakery, market etc. Church has labels like Chapel, Cathedral etc.

enter image description here

The Individuals look like this:

enter image description here

I need to do a SPARQL query, which will retrieve the individuals according to the labels. So let's say I want to get all the individuals of that subclass which has the labels of type seeAlso "bakery". In this case I expect to get bakery1 and supermarket1

I have tried this, but it seems like this query is wrong:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?individual ?class ?label
WHERE { 
    ?individual rdf:type owl:NamedIndividual .
    ?class rdf:type owl:Class .
    FILTER(?label="bakery")
}

If I delete the line with FILTER , I will get only the individuals and classes, but not related to each other as they should. Protege just returns me all the possible connections Class - Individual

Upvotes: 2

Views: 9682

Answers (2)

scotthenninger
scotthenninger

Reputation: 4001

Given comments to the answer, the intent is to build synonyms, not separate instances. There are a few ways to do this, but SKOS is specifically designed for such vocabulary relationships. The property skos:prefLabel is used for the display label, and synonyms can be defined by skos:altLabel. The hierarchy you have can be retained, just use skos:altLabel instead of 'rdf:seeAlso' (which is normally used for reference links ourtide of the ontology).

So the data, in a Turtle text serialization would look like:

:Shop rdfs:subClassOf :Building .
:Shop skos:prefLabel "Shop"^^xsd:string .
:Shop skos:altLabel "supermarket"^^xsd:string .
:Shop skos:altLabel "bakery"^^xsd:string .
:Shop skos:altLabel "market"^^xsd:string .

For the query, the OP says to match by the string - the preflabel in this case:

SELECT ?individual ?label
WHERE {
   ?individual skos:prefLabel "Shop"^^xsd:string .
   ?individual skos:altLabel ?label
}

Upvotes: 3

scotthenninger
scotthenninger

Reputation: 4001

I think what you are looking for is all of the instances of the class :Building and its subclasses. Also note that if ?label is not bound, the filter will always fail. So you'll need to do the following:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>SELECT 
WHERE {
   ?cls rdfs:subClassOf* :Building .
   ?individual a ?cls .
   ?individual rdfs:seeAlso ?label .
   FILTER (?label = "bakery")
}

…and that is a classic anti-pattern for SPARQL. As much as possible, you should use basic graph patterns, so this is a more correct query:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>SELECT 
WHERE {
   ?cls rdfs:subClassOf* :Building .
   ?individual a ?cls .
   ?individual rdfs:seeAlso "bakery" .
}

Note the third triple pattern uses the literal in the triple pattern. Also, I don't think the model you have should be using rdfs:seeAlso for the label of the instance. Instead I'd suggest a separate instance for each kind Shop, etc. and use rdfs:label to represent the label of the instance.

Lastly, if you need to do an inexact match you can use regex. For example to find "bakery" regardless of case, use the following:

#-- …
?individual rdfs:seeAlso ?label .
FILTER regex(?label, "Bakery", "i")

Upvotes: 3

Related Questions