Search code examples
sparqlrdfsemantic-web

How to return subgraph from rdf graph


I have an RDF graph G with several classes assuming for simplicity (Person and Parrot). The class Person is connected to the class Parrot by the property hasAnimal, e.g.:

@PREFIX : <http://example.org/> 

:Hugo rdf:type :Person . 
:Hugo rdfs:label "Hugo" .
:Hugo :hasAnimal :Birdy.
:Birdy rdf:type :Parrot .
:Birdy rdfs:label :"Birdy" .

:LonleyBrido rdf:type :Parrot . 

What is wanted is a subgraph of G that contains all the triples from Person and Parrot that are directly connected with each other, starting from Person. The initial Person does not matter to me, the important part is that only connected triples are extracted i.e. that only persons that do have a parrot or don't get outputted. What I have already tried is the following:

construct {
?person ?p ?o .
?parrot ?p2 ?o2 .
} where {
?person rdf:type :Person .
?person ?p ?o .
?person :hasAnimal ?parrot .
?parrot  rdf:type :Parrot  .
?parrot  ?p2 ?o2 .
}

So the expected output would be:

:Hugo rdf:type :Person . 
:Hugo rdfs:label "Hugo" .
:Hugo :hasAnimal :Birdy.
:Birdy rdf:type :Parrot .
:Birdy rdfs:label :"Birdy" .

I am executing this query on a rdflib graph. Does anyone have a solution to this problem?


Solution

  • The solution is already described above:

    import rdflib
    from rdflib.namespace import RDF, RDFS
    
    query = """
    construct {
    ?person ?p ?o .
    ?parrot ?p2 ?o2 .
    } where {
    ?person rdf:type :Person .
    ?person ?p ?o .
    ?person :hasAnimal ?parrot .
    ?parrot  rdf:type :Parrot  .
    ?parrot  ?p2 ?o2 .
    }
    """
    
    g = rdflib.Graph()
    g.parse("example.ttl", format="ttl")
    g.bind("rdf", RDF)
    g.bind("rdfs", RDFS)
    EX= rdflib.Namespace("http://example.org/")
    g.bind("example", EX)
    result = g.query(query)