SPARQL tips and tricks
In 2013, SPARQL 1.1 introduced a new feature, namely "property paths", to enable compact queries. As it’s a standard feature in SPARQL 1.1, most triple stores claiming to support SPARQL 1.1 should support this as well. In that regard, this paper might also be of interest:
Skubella, Adrian, Janke, Daniel and Staab, Steffen (2019) BeSEPPI: Semantic-based benchmarking of property path implementations. The Semantic Web - 15th International Conference, Portoroz, Slovenia. 02 - 06 Jun 2019. pp. 475-490. Preprint: https://eprints.soton.ac.uk/429356/ Paper: https://doi.org/10.1007/978-3-030-21348-0_31
Below are two simple examples of how to use different syntax provided by the "property paths". There’s more functions/syntax that might be of help under this feature, for more information, please visit https://www.w3.org/TR/sparql11-query/#propertypaths.
In the syntax of "property paths", one frequently used symbol is /
, which indicates the SequencePath
between concepts and it allows us to write compact queries. For example, we have a reaction conducted at a reaction condition of residence time, i.e.
PREFIX OntoRxn: <https://github.com/cambridge-cares/TheWorldAvatar/blob/develop/JPS_Ontology/ontology/ontorxn/OntoRxn.owl#>
PREFIX exp1: <https://theworldavatar.com/kb/ontorxn/ReactionExperiment_1/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX om: <http://www.ontology-of-units-of-measure.org/resource/om-2/>
exp1:RxnExp_1
rdf:type OntoRxn:ReactionExperiment;
OntoRxn:hasResTime exp1:ResidenceTime_1;
.
If you are working with dimensional quantities following OM (units of measure) practices, the complete triples about exp1:ResidenceTime_1
should be:
OntoRxn:ResidenceTime rdf:type om:Duration .
exp1:ResidenceTime_1
rdf:type OntoRxn:ResidenceTime;
om:hasPhenomenon exp1:RxnExp_1;
om:hasValue exp1:ResidenceTime_1_Measure_1;
.
exp1:ResidenceTime_1_Measure_1
rdf:type om:Measure;
om:hasUnit om:minute-Time;
om:hasNumericalValue "8.1"^^xsd:double;
.
To retrieve the numerical value of the residence time, we normally write a SPARQL query string like:
PREFIX OntoRxn: <https://github.com/cambridge-cares/TheWorldAvatar/blob/develop/JPS_Ontology/ontology/ontorxn/OntoRxn.owl#>
PREFIX exp1: <https://theworldavatar.com/kb/ontorxn/ReactionExperiment_1/>
PREFIX om: <http://www.ontology-of-units-of-measure.org/resource/om-2/>
SELECT ?res_time ?unit
WHERE {
exp1:RxnExp_1 OntoRxn:hasResTime ?res .
?res om:hasValue ?measure .
?measure om:hasNumericalValue ?res_time ;
om:hasUnit ?unit .
}
which will return results as:
res_time | unit |
---|---|
8.1 | <http://www.ontology-of-units-of-measure.org/resource/om-2/minute-Time> |
The same results can be retrieved by writing compact queries using /
, i.e.
PREFIX OntoRxn: <https://github.com/cambridge-cares/TheWorldAvatar/blob/develop/JPS_Ontology/ontology/ontorxn/OntoRxn.owl#>
PREFIX exp1: <https://theworldavatar.com/kb/ontorxn/ReactionExperiment_1/>
PREFIX om: <http://www.ontology-of-units-of-measure.org/resource/om-2/>
SELECT ?res_time ?unit
WHERE {
exp1:RxnExp_1 OntoRxn:hasResTime/om:hasValue ?measure .
?measure om:hasNumericalValue ?res_time ;
om:hasUnit ?unit .
}
Above is only a simple example, the SequencePath
(/
) will be more useful when we want to query a deep ontology.
Another frequently used symbol is +
, which indicates the OneOrMorePath
between concepts. This is particularly useful in querying the instances within a class hierarchy. For example, we have a hierarchy of concepts and their corresponding instances about Asset
, i.e.
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX tbox: <http://www.example.com/tbox#>
PREFIX abox: <http://www.example.com/abox/>
# TBox class hierarchy
tbox:Asset rdf:type owl:Class .
tbox:TangibleAsset rdfs:subClassOf tbox:Asset .
tbox:PropertyAndPlant rdfs:subClassOf tbox:TangibleAsset .
tbox:EcoIndustrialPark rdfs:subClassOf tbox:PropertyAndPlant .
tbox:ChemicalPlant rdfs:subClassOf tbox:EcoIndustrialPark .
tbox:Vehicles rdfs:subClassOf tbox:TangibleAsset .
tbox:Car rdfs:subClassOf tbox:Vehicles .
tbox:Flight rdfs:subClassOf tbox:Vehicles .
tbox:IntangibleAsset rdfs:subClassOf tbox:Asset .
tbox:Patent rdfs:subClassOf tbox:IntangibleAsset .
tbox:PatentAtEPO rdfs:subClassOf tbox:Patent .
tbox:PatentAtWIPO rdfs:subClassOf tbox:Patent .
# ABox instances of class hierarchy
abox:Asset_101 rdf:type tbox:Asset .
abox:TangibleAsset_101 rdf:type tbox:TangibleAsset .
abox:Properties_101 rdf:type tbox:PropertyAndPlant .
abox:JurongIslandPark rdf:type tbox:EcoIndustrialPark .
abox:ChemicalPlant_101 rdf:type tbox:ChemicalPlant .
abox:TransportVehicle_101 rdf:type tbox:Vehicles .
abox:Bus_101 rdf:type tbox:Car .
abox:Flight_101 rdf:type tbox:Flight .
abox:IntangibleAsset_101 rdf:type tbox:IntangibleAsset .
abox:FilledPatent_101 rdf:type tbox:Patent .
abox:Patent_1 rdf:type tbox:PatentAtEPO .
abox:Patent_2 rdf:type tbox:PatentAtWIPO .
and we want to answer a question like:
What’re all the assets under the class Asset
?
By using OneOrMorePath
(+
), all instances instantiated from the Asset
concept can be queried using one simple SPARQL query string, i.e.
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX tbox: <http://www.example.com/tbox#>
SELECT ?asset
WHERE {
?asset rdf:type/rdfs:subClassOf+ tbox:Asset .
}
giving results:
asset |
---|
<http://www.example.com/abox/Bus_101> |
<http://www.example.com/abox/ChemicalPlant_101> |
<http://www.example.com/abox/JurongIslandPark> |
<http://www.example.com/abox/Flight_101> |
<http://www.example.com/abox/IntangibleAsset_101> |
<http://www.example.com/abox/FilledPatent_101> |
<http://www.example.com/abox/Patent_1> |
<http://www.example.com/abox/Patent_2> |
<http://www.example.com/abox/Properties_101> |
<http://www.example.com/abox/TangibleAsset_101> |
<http://www.example.com/abox/TransportVehicle_101> |
A similar query can be done to query the hierarchy of object properties, for example, if we have a set of object properties declared as:
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX tbox: <http://www.example.com/tbox#>
PREFIX abox: <http://www.example.com/abox/>
# TBox relationship hierarchy
tbox:hasCharacteristic rdf:type rdfs:Property .
tbox:hasDimension rdfs:subPropertyOf tbox:hasCharacteristic .
tbox:hasLength rdfs:subPropertyOf tbox:hasDimension .
tbox:hasLengthInMeters rdfs:subPropertyOf tbox:hasLength .
tbox:hasLengthInInches rdfs:subPropertyOf tbox:hasLength .
tbox:hasBrand rdfs:subPropertyOf tbox:hasCharacteristic .
tbox:hasName rdfs:subPropertyOf tbox:hasCharacteristic .
tbox:hasFullName rdfs:subPropertyOf tbox:hasName .
tbox:hasFirstName rdfs:subPropertyOf tbox:hasFullName .
tbox:hasLastName rdfs:subPropertyOf tbox:hasFullName .
and again, we are interested to answer questions like:
What’s all the subproperties under the property hasCharacteristic
?
A simple query can be used to answer this question:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX tbox: <http://www.example.com/tbox#>
SELECT ?properties
WHERE {
?properties rdfs:subPropertyOf+ tbox:hasCharacteristic .
}
giving results:
properties |
---|
<http://www.example.com/tbox#hasBrand> |
<http://www.example.com/tbox#hasDimension> |
<http://www.example.com/tbox#hasName> |
<http://www.example.com/tbox#hasLength> |
<http://www.example.com/tbox#hasFullName> |
<http://www.example.com/tbox#hasFirstName> |
<http://www.example.com/tbox#hasLastName> |
<http://www.example.com/tbox#hasLengthInInches> |
<http://www.example.com/tbox#hasLengthInMeters> |
- Home
- FAQ
- How to contribute
- Development guidelines:
- Containerisation:
- Examples
- Handling data:
- Visualisations: