I'm transforming the data in one data store to another form / ontology / schema, using SPARQL.
The data is actually a provenance, but can be simplified as a series of relationship like this: A produces D
+ B consumes D
.
:A0 :consumes :D0 ;
:produces :D1, :D2 .
:A1 :produces :D3 .
:A2 :consumes :D1, :D2 ;
:produces :D4 .
:A3 :consumes :D3, :D4 ;
:produces :D5, D6 .
(There is no guarantee D is always produced by some A, or will be consumed by some other A. But every D will only be produced by one A.)
I would like to get the information of data dependency. An example query looks like this:
CONSTRUCT {
?producer :hasNextStage ?consumer .
}
WHERE {
?producer :produces ?data .
OPTIONAL {
?consumer :consumes ?data .
FILTER (?producer != ?consumer)
}
}
Everything is fine until here. However, I would like to have more information, say "which A is connected to which another A by what data", something like this:
:A0 :hasInfluence :INFLUENCE .
:INFLUENCE :stage :A2 ;
:data :D1, :D2 .
As demonstrated, this requires me to construct a new variable (:INFLUENCE
) and assign triples to it.
Is there a way to do this in SPARQL?
------ UPDATED SECONDARY QUESTION ------
According to cygri's answer, I changed the query to this:
CONSTRUCT {
?producer :hasInfluence ?influence .
?influence :stage ?consumer ;
:data ?data .
}
WHERE {
?producer :produces ?data .
OPTIONAL {
?consumer :consumes ?data .
FILTER (?producer != ?consumer)
BIND (IRI(CONCAT("http://my/ns/#", CONCAT(STRAFTER(STR(?producer), "#"), STRAFTER(STR(?consumer), "#")))) AS ?influence)
}
}
However, the BIND
clause seems not having any effect. After shortening it, the problem is with the ?producer
variable: if I use this variable here, it won't work. Seems ?producer
is not bound here? (But the FILTER
does work.)
If I move this BIND
clause out of the OPTIONAL
, everything works fine. But this is not intuitive, and I'm wondering why it won't work inside OPTIONAL
?
IRI()
to create a URI resource from a string. Or just put the IRI there if you know it – UninformedUser Apr 1 '19 at 17:08OPTIONAL
is a left-outer join during evaluation. The clause is evaluated separately. Read about scope of variables: w3.org/TR/sparql11-query/#variableScope – UninformedUser Apr 2 '19 at 12:10(leftjoin (bgp (triple ?producer <http://ex.org/test/produces> ?data)) (extend ((?influence (iri (concat "http://my/ns/#" (concat (strafter (str ?producer) "#") (strafter (str ?consumer) "#")))))) (bgp (triple ?consumer <http://ex.org/test/consumes> ?data))) (!= ?producer ?consumer))
– UninformedUser Apr 2 '19 at 12:17BIND
outside of theOPTIONAL
:(extend ((?influence (iri (concat "http://my/ns/#" (concat (strafter (str ?producer) "#") (strafter (str ?consumer) "#")))))) (conditional (bgp (triple ?producer <http://ex.org/test/produces> ?data)) (filter (!= ?producer ?consumer) (bgp (triple ?consumer <http://ex.org/test/consumes> ?data)))))
– UninformedUser Apr 2 '19 at 12:18BIND
and the scope: blog.blazegraph.com/?p=954 - and I agree, without knowing this, it is definitely confusing – UninformedUser Apr 2 '19 at 12:19