Search code examples
sparqlrdf

SPARQL arbitrary-length property path query with arbitrary but directed properties


Lets's say I have the following RDF graph:

@prefix :  <http://example/> .

:order1  :item :z1 .
:order2  :item :z2 .

:z1 :name "Small" .
:z1 :price 5 .

:z2 :name "Large" .
:z2 :price 5 .

I want a SPARQL query to select all triples that describe :z1. i.e. all triples that are children or children of children (etc.) of :z1. So far from what I found this is called an arbitrary-length property path with arbitrary properties. I have used solutions from SPARQL property path queries with arbitrary properties and Sparql - query to get all triples related to a specific subject to come up with this query:

PREFIX : <http://example/>
SELECT ?s ?p ?o
WHERE {
    ?s ?p ?o .
    :order1 (<>|!<>)+ ?o .  # Match arbitrary-length property path with arbitrary properties 
}

Which results in (in ttl format):

@prefix : <http://example/> .

:order1 :item :z1 .

:z2 :price 5 .

:z1 :name "Small" ;
    :price 5 .

As you can see this also selects the :z2 :price 5 . triple, which I did not expect and is also not what I want. For some reason, it seems like the inverse :price path inference from object 5 to subject :z2 is also included.

How do I achieve selecting all triples included in the arbitrary-length property path of :z1 with arbitrary but directed properties?

NB: This is a simplified version of the real problem I try to solve where the predicates in the path and the length of the path can indeed be arbitrary.

Perhaps this drawing helps: Visualisation of the problem


Solution

  • As mentioned by @UninformedUser I was getting all incoming edges starting from :order1, whereas I want all outcoming edges.

    The correct query would be:

    PREFIX : <http://example/>
    SELECT ?s ?p ?o
    WHERE {
        ?s ?p ?o .
        :order1 (<>|!<>)* ?s .  # Match arbitrary-length property path with arbitrary properties 
    }
    

    Where I changed ?o to ?s in :order1 (<>|!<>)+ ?o . so I only match outgoing edges, i.e. triples on the path where the subject (?s) is the target of a 'mother' triple.

    I also changed + to * in :order1 (<>|!<>)+ ?o . so I match paths of length 0 or more instead of 1 or more so I also get the triples where :order1 is the subject.