'Is there a way to query using SPARQL for more than one value of object when the subject and predicate are the same?

For context I am using GraphDB (SPARQL 1.1), and I have extended the What To Make ontology. I'd like to construct a query that can select ONLY the subjects that contain all of the objects with matching values for a particular predicate.

In my data (below) selecting the individual &so;KitchenDrawer's so:contains predicates and matching those against only those '&wtm;Recipe''s that contain just the values for wtm:hasIngredient. The subject and predicate are the same but there are alternating objects.

When I run the query (with &so;KitchenDrawer only containing &ind;Basil and &ind;Tomato), I would like to only get the subject's &ind;JustTomatoAndBasil and &ind;JustTomato, omitting &ind;Pesto as it has ingredients other than basil and tomato.

RDF Data:

<?xml version="1.0"?>

<!DOCTYPE rdf:RDF [
    <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
    <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
    <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
    <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
    <!ENTITY dct "http://purl.org/dc/terms/" >
    <!ENTITY obo "http://purl.obolibrary.org/obo/" >
    <!ENTITY skos "http://www.w3.org/2004/02/skos/core#" > 
    <!ENTITY wtm "http://purl.org/heals/food/" >
    <!ENTITY ind "http://purl.org/heals/ingredient/" >
    <!ENTITY prov "http://www.w3.org/ns/prov#">
    <!ENTITY sm "http://www.omg.org/techprocess/ab/SpecificationMetadata/">
    <!ENTITY so "http://example.com/storage-ontology/">
]>

<rdf:RDF xml:base="http://purl.org/heals/ingredient/"
     xmlns:so="http://example.com/storage-ontology/"
     xmlns:wtm="http://purl.org/heals/food/"
     xmlns:dct="http://purl.org/dc/terms/"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xml="http://www.w3.org/XML/1998/namespace"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:skos="http://www.w3.org/2004/02/skos/core#"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:obo="http://purl.obolibrary.org/obo/"
     xmlns:prov="http://www.w3.org/ns/prov#"
     xmlns:ind="http://purl.org/heals/ingredient/"
     xmlns:sm="https://www.omg.org/techprocess/ab/SpecificationMetadata/">
    <owl:Ontology rdf:about="http://purl.org/heals/ingredient/">
        <owl:imports rdf:resource="http://purl.org/heals/food/"/>
        <owl:imports rdf:resource="http://www.omg.org/techprocess/ab/SpecificationMetadata/"/>
        <rdfs:label>What to Make Individuals Extensions</rdfs:label>
        <dct:license rdf:datatype="&xsd;anyURI">http://opensource.org/licenses/MIT</dct:license>
    </owl:Ontology>
    
    <owl:NamedIndividual rdf:about="&ind;JustTomato">
        <rdf:type rdf:resource="&wtm;Recipe"/>
        <wtm:hasIngredient rdf:resource="&ind;Tomato"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Lunch"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Dinner"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Snack"/>
        <skos:scopeNote>recipe</skos:scopeNote>
    </owl:NamedIndividual>
    
    <owl:NamedIndividual rdf:about="&ind;JustTomatoAndBasil">
        <rdf:type rdf:resource="&wtm;Recipe"/>
        <wtm:hasIngredient rdf:resource="&ind;Tomato"/>
        <wtm:hasIngredient rdf:resource="&ind;Basil"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Lunch"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Dinner"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Snack"/>
        <skos:scopeNote>recipe</skos:scopeNote>
    </owl:NamedIndividual>
    
    <owl:NamedIndividual rdf:about="&ind;Pesto">
        <rdf:type rdf:resource="&wtm;Recipe"/>
        <wtm:hasIngredient rdf:resource="&ind;Basil"/>
        <wtm:hasIngredient rdf:resource="&ind;PineNuts"/>   
        <wtm:hasIngredient rdf:resource="&ind;Parmesan"/>
        <wtm:hasIngredient rdf:resource="&ind;Garlic"/>
        <wtm:hasIngredient rdf:resource="&ind;OliveOil"/>       
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Lunch"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Dinner"/>
        <wtm:isRecommendedForMeal rdf:resource="&wtm;Snack"/>
        <wtm:serves rdf:datatype="&xsd;integer">4</wtm:serves>
        <rdfs:label>basil pesto</rdfs:label>
        <skos:definition>a traditional pesto made from paresan cheese and basil</skos:definition>
        <skos:scopeNote>recipe</skos:scopeNote>
    </owl:NamedIndividual>
    
    
    <owl:Class rdf:about="&so;StorageLocation">
    </owl:Class>
        
    <owl:Class rdf:about="&so;Drawer">
        <rdfs:subClassOf rdf:resource="&so;StorageLocation"/>
    </owl:Class>
        
    <owl:ObjectProperty rdf:about="&so;contains">
    </owl:ObjectProperty>
        
    <owl:NamedIndividual rdf:about="&so;KitchenDrawer">
        <rdf:type rdf:resource="&so;Rack"/>
        <so:contains rdf:resource="&ind;Basil"></so:contains>
        <so:contains rdf:resource="&ind;Tomato"></so:contains>
    </owl:NamedIndividual>
    
</rdf:RDF>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source