- From: Axel Polleres <axel.polleres@deri.org>
- Date: Tue, 19 May 2009 12:45:02 +0100
- To: 'RDF Data Access Working Group' <public-rdf-dawg@w3.org>
This completes Action-20:
http://www.w3.org/2009/sparql/track/actions/20
I promised in the F2F to send a use case to the list on using nested
CONSTRUCT queries in FROM clauses.
Here we go
(BTW: we should talk about where/how to collect these use cases on the wiki)
=====================================================================
The scenario is as follows. You have some RDF representation about
publications available that uses dc:creator links to link publications
to the names of their authors.
Graph <g>:
<http://ex.org/papers#p1> dc:creator "Alice" .
<http://ex.org/papers#p1> dc:creator "Bob" .
<http://ex.org/papers#p1> dc:creator "Charles" .
We want to translate that data to FOAF extracting social network
informaiton saying that each two persons who co-authored an article know
each other.
We have to use blank nodes for denoting authors, since we have only
their name.
The naive query
CONSTRUCT
{ _:a foaf:knows _:b . _:a foaf:name ?n1 . _:b foaf:name ?n2 . }
FROM <g>
WHERE { ?p dc:creator ?n1 . ?p dc:creator ?n2 . FILTER ( ?n1 != ?n2 ) }
wouldn't work as desired, because the solution would assign different
blank nodes for eaach solution, loosing the co-reference between authors
of the same paper:
_:a1 foaf:knows _:b1. _:a1 foaf:name "Alice". _:b1 foaf:name "Bob".
_:a2 foaf:knows _:b2. _:a2 foaf:name "Alice". _:b2 foaf:name "Charles".
_:a3 foaf:knows _:b3. _:a3 foaf:name "Bob". _:b3 foaf:name "Charles".
_:a4 foaf:knows _:b4. _:a1 foaf:name "Bob". _:b1 foaf:name "Alice".
_:a5 foaf:knows _:b5. _:a2 foaf:name "Charles". _:b2 foaf:name "Alice".
_:a6 foaf:knows _:b6. _:a3 foaf:name "Charles". _:b3 foaf:name "Bob".
The following query, using nested CONSTRUCTs in the FROM clause, solves
this problem by creating a bnode for each paper-author-pair in the first
step and only in a second step creating the foaf:knows links between
these blank noedes:
CONSTRUCT { ?a knows ?b . ?a foaf:name ?aname . ?b foaf:name ?bname . }
FROM {
CONSTRUCT { _:a foaf:name ?n . ?p aux:hasAuthor _:a . }
FROM <g>
WHERE { ?p dc:creator ?n . }
}
WHERE
{ ?p aux:hasAuthor ?a . ?a foaf:name ?aname .
?p aux:hasAuthor ?b . ?b foaf:name ?bname .
FILTER ( ?a != ?b ) }
Result:
_:a1 foaf:knows _:a2. _:a1 foaf:name "Alice". _:a2 foaf:name "Bob".
_:a1 foaf:knows _:a3. _:a1 foaf:name "Alice". _:a3 foaf:name "Charles".
_:a2 foaf:knows _:a3. _:a2 foaf:name "Bob". _:a3 foaf:name "Charles".
_:a2 foaf:knows _:a1. _:a2 foaf:name "Bob". _:a1 foaf:name "Alice".
_:a3 foaf:knows _:a1. _:a3 foaf:name "Charles". _:a1 foaf:name "Alice".
_:a3 foaf:knows _:a2. _:a3 foaf:name "Charles". _:a2 foaf:name "Bob".
As easily observed, the second result preserves the coreference
between blank nodes and names of authors of the same papers.
=================================================================
Received on Tuesday, 19 May 2009 11:45:45 UTC