S M Shamimul Hasan
S M Shamimul Hasan

Reputation: 6674

SPARQL Transitive Query with Unique Predicates

I have a number of triples organized like following.

:A :hasB :B
:B :hasC :C
:C :hasD :D
:D :hasE :E
............
:X :hasY :Y 
:Y :hasZ :Z

All the predicates are unique.

I need to write two SPARQL queries.

Query 1 will find all the predicates between :A to :Z through a transitive query (something like this :A :has* :Z). Output 1 should look like following.

Output 1:
--------
hasB
hasC
hasD
....
hasZ

Ouery 2 will find triples between :A to :Z through a transitive query. Output 2 should look like following.

Output 2:
--------
:B :hasC :C
:C :hasD :D
:D :hasE :E
............
:X :hasY :Y

Please let me know how to write these transitive SPARQL queries.

Upvotes: 1

Views: 547

Answers (1)

UninformedUser
UninformedUser

Reputation: 8465

SPARQL has some obvious limitations as it's not a graph query language. Possible solutions below:

If there are no other predicates besides has[A-Z]:

Sample Data

@prefix : <http://ex.org/> .
:A :hasB :B .
:B :hasC :C .
:C :hasD :D .
:D :hasE :E .

Query

prefix : <http://ex.org/>
select ?p
where {
values (?start ?end) { (:A :E) }
  ?start (<p>|!<p>)* ?v1 .
  ?v1 ?p ?v2 .
  ?v2 (<p>|!<p>)* ?end .
}

Output

---------
| p     |
=========
| :hasB |
| :hasC |
| :hasD |
| :hasE |
---------

If there are other predicates besides has[A-Z]:

Sample Data

@prefix : <http://ex.org/> .
:A :hasB :B .
:B :hasC :C .
:C :hasD :D .
:C :notHasD :D .
:D :hasE :E .
  1. Introduce a super property :has:

    Additional Data:

    @prefix : <http://ex.org/> .
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    :hasB rdfs:subPropertyOf :has .
    :hasC rdfs:subPropertyOf :has .
    :hasD rdfs:subPropertyOf :has .
    :hasE rdfs:subPropertyOf :has .
    

    Query:

    prefix : <http://ex.org/>
    prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    select ?p
    where {
    values (?start ?end) { (:A :E) }
      ?start (<p>|!<p>)* ?v1 .
      ?v1 ?p ?v2 . ?p rdfs:subPropertyOf :has .
      ?v2 (<p>|!<p>)* ?end .
    }
    

    Output

    ---------
    | p     |
    =========
    | :hasB |
    | :hasC |
    | :hasD |
    | :hasE |
    ---------
    
  2. Use REGEX on property URI:

    prefix : <http://ex.org/>
    select ?p
    where {
      values (?start ?end) { (:A :E) }
      ?start (<p>|!<p>)* ?v1 .
      ?v1 ?p ?v2 . 
      FILTER(REGEX(STRAFTER(STR(?p), STR(:)), 'has[A-Z]'))
      ?v2 (<p>|!<p>)* ?end .
    }
    

Note, all the proposed solutions will not work on all kind of data, especially once you have multiple paths and/or cycles. In that case, you should use a proper graph database.

Upvotes: 1

Related Questions