[ACTION-20] a query using CONSTRUCT in the FROM clause.

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