Search code examples
sparqlowl

best practice regarding separation of ontology and data for SPARQL queries?


I'm working on an ontology and a linked open dataset that uses it. I am using Protégé 5.5.0 on a Mac. I have tried running SPARQL queries in Protégé and I have been using stain/jena-fuseki on docker as well.

I would like to separate the ontology (contained in vocab.owl) from the data (data.ttl)

In vocab.owl, I have created classes Item and Scale. An Item has a Scale, one of 1_One, 2_Two, and 3_Three. Each Scale has a value and a label.

vocab.owl

@prefix tst: <http://www2.cs.uregina.ca/~hepting/vocab.owl#> .
@prefix : <http://www2.cs.uregina.ca/~hepting/data.ttl#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www2.cs.uregina.ca/~hepting/vocab.owl> .

<http://www2.cs.uregina.ca/~hepting/vocab> rdf:type owl:Ontology .

#################################################################
#    Object Properties
#################################################################

tst:hasScale rdf:type owl:ObjectProperty .

#################################################################
#    Data properties
#################################################################

tst:hasScale rdf:type owl:DatatypeProperty .

tst:hasScaleLabel rdf:type owl:DatatypeProperty ;
               rdfs:subPropertyOf tst:hasScale .

tst:hasScaleValue rdf:type owl:DatatypeProperty ;
               rdfs:subPropertyOf tst:hasScale .

#################################################################
#    Classes
#################################################################

tst:Item rdf:type owl:Class ;
      rdfs:subClassOf [ rdf:type owl:Restriction ;
                        owl:onProperty tst:hasScale ;
                        owl:someValuesFrom tst:Scale
                      ] .

tst:Scale rdf:type owl:Class ;
       owl:equivalentClass [ rdf:type owl:Class ;
                             owl:oneOf ( tst:1_One
                                         tst:2_Two
                                         tst:3_Three
                                       )
                           ] .

#################################################################
#    Named Individuals
#################################################################

tst:1_One a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "1"^^xsd:positiveInteger ;
      tst:hasScaleLabel "One"^^xsd:string .

tst:2_Two a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "2"^^xsd:positiveInteger ;
      tst:hasScaleLabel "Two"^^xsd:string .

tst:3_Three a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "3"^^xsd:positiveInteger ;
      tst:hasScaleLabel "Three"^^xsd:string .

In data.ttl, I have created 7 instances of Item, that each have an instance of Scale.

data.ttl:

@prefix tst: <http://www2.cs.uregina.ca/~hepting/vocab.owl#> .
@prefix : <http://www2.cs.uregina.ca/~hepting/data.ttl#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

:Item1 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:1_One .

:Item2 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:2_Two .

:Item3 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:3_Three .

:Item4 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:3_Three .

:Item5 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:3_Three .

:Item6 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:3_Three .

:Item7 a owl:NamedIndividual , tst:Item ;
    tst:hasScale tst:3_Three .

I want to run a query that associates Items with ScaleValues.

query:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX tst: <http://www2.cs.uregina.ca/~hepting/vocab.owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX : <http://www2.cs.uregina.ca/~hepting/data.ttl#>

SELECT * WHERE
{
  ?item tst:hasScale ?scale .
  ?scale tst:hasScaleValue ?value .
}
ORDER BY ?scale

In docker stain/jena-fuseki, I load data.ttl into a dataset (21 triples) and my query above has no errors but returns no results. (The results are similar if I use the SPARQL Query tab to execute my query in Protégé with data.ttl loaded)

If I edit my dataset in docker stain/jena-fuseki to add the following:

tst:1_One a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "1"^^xsd:positiveInteger ;
      tst:hasScaleLabel "One"^^xsd:string .

tst:2_Two a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "2"^^xsd:positiveInteger ;
      tst:hasScaleLabel "Two"^^xsd:string .

tst:3_Three a owl:NamedIndividual , tst:Scale ;
      tst:hasScaleValue "3"^^xsd:positiveInteger ;
      tst:hasScaleLabel "Three"^^xsd:string .

to give 33 triples, I get the following raw results for my query -- 1 entry for each of the 7 items in data.ttl (the desired results):

{
  "head": {
    "vars": [ "item" , "scale" , "value" ]
  } ,
  "results": {
    "bindings": [
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item1" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#1_One" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "1" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item2" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#2_Two" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "2" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item3" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#3_Three" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "3" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item4" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#3_Three" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "3" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item5" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#3_Three" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "3" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item6" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#3_Three" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "3" }
      } ,
      {
        "item": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/data.ttl#Item7" } ,
        "scale": { "type": "uri" , "value": "http://www2.cs.uregina.ca/~hepting/vocab.owl#3_Three" } ,
        "value": { "type": "literal" , "datatype": "http://www.w3.org/2001/XMLSchema#positiveInteger" , "value": "3" }
      }
    ]
  }
}

Returning to the 21 triples in the data.ttl file, I tried the following query (with the addition of FROMs) that returned no data.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX tst: <http://www2.cs.uregina.ca/~hepting/vocab.owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX : <http://www2.cs.uregina.ca/~hepting/data.ttl#>

SELECT * 
FROM <http://www2.cs.uregina.ca/~hepting/vocab.owl>
FROM <http://www2.cs.uregina.ca/~hepting/data.ttl>
WHERE
{
  ?s ?p ?o
}

Is there a way to get the desired results while maintaining the separation between vocab.owl and data.ttl?


Solution

  • You have to upload both Turtle files (the data and the ontology) to Fuseki.

    A potential pitfall: Fuseki doesn’t allow uploading Turtle files with the extension .owl. Unfortunately, it fails somewhat silently, by coloring the progress bar in red, and printing "Triples uploaded: 0".

    Fuseki UI: when trying to upload a Turtle file with the extension '.owl', the progress bar is colored red instead of green, and the text says that it has uploaded 0 triples

    After renaming the ontology to vocab.ttl, and uploading it, the first query from your question works as expected:

    SPARQL query result, showing 7 results/lines