1

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.

Beautiful Mind
  • 5,828
  • 4
  • 23
  • 42
  • 1
    That is not possible with your current data. You can't have regex pattern in a property path expression. One workaround would be to introduce a super property `:has` and use this in the query. If your data doesn't have other properties you could also try to use the wildcard pattern `

    |!

    ` and query for paths.

    – UninformedUser Nov 22 '17 at 05:12
  • I know you ignore this comment again, but: You have **never** accepted any answer to your questions. That is not how StackOverflow works, sorry. – UninformedUser Nov 22 '17 at 05:13
  • Thanks for your help. Just accept one answer. I will do more soon. – Beautiful Mind Nov 22 '17 at 05:40
  • Regarding your question. Is it an option to add the super property `:has` ? – UninformedUser Nov 22 '17 at 07:51

1 Answers1

1

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.

UninformedUser
  • 8,397
  • 1
  • 14
  • 23