Search code examples
sparqlowlontologygraphdbrdfs

Get list of instances matching the intersection of all restriction values


I just started learning how to work with ontologies and make SPARQL queries. I am using a merged copy of these 2 ontologies - wine and food in GraphDB with OWL-Max ruleset.

I want to get a list of all suitable wines for a given meal. A meal could have a different number of restrictions. I found a similar question and managed to get a list of the active restrictions, but I don't know how to query wines that have all of the values combined.

Is there a way to intersect the wines with the restrictions list result? Should I somehow bind the list values - each property and the corresponding value, so I can query them together or do something like in the answer here?

Definition of the property hasDrink, which determines the suitable wines:

  <owl:ObjectProperty rdf:ID="hasDrink">
    <rdfs:domain rdf:resource="#MealCourse" />
    <rdfs:range rdf:resource="#PotableLiquid" />
  </owl:ObjectProperty>

Example meal:

<owl:Class rdf:ID="PastaWithNonSpicyRedSauceCourse">
<owl:intersectionOf rdf:parseType="Collection">
  <owl:Class rdf:about="#MealCourse" />
  <owl:Restriction>
    <owl:onProperty rdf:resource="#hasFood" />
    <owl:allValuesFrom rdf:resource="#PastaWithNonSpicyRedSauce" />
  </owl:Restriction>
</owl:intersectionOf>
<rdfs:subClassOf>
  <owl:Restriction>
    <owl:onProperty rdf:resource="#hasDrink" />
    <owl:allValuesFrom>
      <owl:Restriction>
        <owl:onProperty rdf:resource="#hasColor" />
        <owl:hasValue rdf:resource="#Red" />
      </owl:Restriction>
    </owl:allValuesFrom>
  </owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
  <owl:Restriction>
    <owl:onProperty rdf:resource="#hasDrink" />
    <owl:allValuesFrom>
      <owl:Restriction>
        <owl:onProperty rdf:resource="#hasBody" />
        <owl:hasValue rdf:resource="#Medium" />
      </owl:Restriction>
    </owl:allValuesFrom>
  </owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
  <owl:Restriction>
    <owl:onProperty rdf:resource="#hasDrink" />
    <owl:allValuesFrom>
      <owl:Restriction>
        <owl:onProperty rdf:resource="#hasFlavor" />
        <owl:hasValue rdf:resource="#Moderate" />
      </owl:Restriction>
    </owl:allValuesFrom>
  </owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
  <owl:Restriction>
    <owl:onProperty rdf:resource="#hasDrink" />
    <owl:allValuesFrom>
      <owl:Restriction>
        <owl:onProperty rdf:resource="#hasSugar" />
        <owl:hasValue rdf:resource="#Dry" />
      </owl:Restriction>
    </owl:allValuesFrom>
  </owl:Restriction>
</rdfs:subClassOf>
</owl:Class>

This is my query so far, but the result gives all of the wines which fulfill at least one of the requirements.

prefix wine:<http://wine-food.com/project#> 
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

SELECT ?w WHERE { 
    ?w a wine:Wine .
    ?w ?p ?val {

       SELECT ?p ?val WHERE { 
           wine:PastaWithNonSpicyRedSauceCourse rdfs:subClassOf ?restriction . 
           ?restriction owl:onProperty wine:hasDrink. 
           ?restriction owl:allValuesFrom [owl:onProperty ?p; owl:hasValue ?val]. 
      } 
   }
}

For the given meal, these are the restrictions, which define if a wine is suitable for it.

p val
:hasColor :Red
:hasBody :Medium
:hasFlavor :Moderate
:hasSugar :Dry

Solution

  • Thanks to the comment of UninformedUser, the problem has been solved by using the pattern "give me all wines where there is no restriction of PastaWithNonSpicyRedSauceCourse that does not exist" like this:

    PREFIX wine:<http://wine-food.com/project#> 
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX owl: <http://www.w3.org/2002/07/owl#>
    
    SELECT ?w WHERE { 
        ?w a wine:Wine .
        filter not exists {       
            wine:PastaWithNonSpicyRedSauceCourse rdfs:subClassOf 
                     [owl:onProperty wine:hasDrink ; owl:allValuesFrom [owl:onProperty ?p; owl:hasValue ?val]] .       
            filter not exists {  
                ?w ?p ?val      
            }    
        }
    }