I promised Danny that I’d write this up, so here’s to making good on promises.
Open Anzo is a quad store. (I’ve written about this before.) All of the services Open Anzo offers—versioning, replication, real-time updates, access control, etc.—are oriented around named graphs. Time and time again we’ve found named graphs to be invaluable in building applications atop an RDF repository.
And while SPARQL took the first steps towards standardizing quads via the named graphs component of the RDF dataset, the CONSTRUCT query result form only returned triples.
For our purposes in Open Anzo, this severely limits the usefulness of CONSTRUCT. We can’t use it to pull out a subset of the server’s data, as any data returned has been stripped of its named graph component. The solution was pretty simple, and is a good example of practicing what I’ve been preaching recently: a key part of the standards process is for implementations to extend the standards.
In this case, we simply extended Glitter’s (Open Anzo’s SPARQL engine) CONSTRUCT templates to support a GRAPH clause, in exactly the same way that SPARQL query patterns support GRAPH clauses. This means that any triple pattern within a CONSTRUCT template will now either output a triple (if its outside any GRAPH clause) or a quad (if its inside a GRAPH clause).
Key to making this happen is the fact that both the Open Anzo server and the three client APIs (Java, JavaScript, and .NET) support serializing and deserializing quads to/from the TriG RDF serialization format. TriG’s a very straightforward extension of Turtle, and I’d like to see it used more and more throughout Semantic Web circles.
Anyway, here are a few simple examples of CONSTRUCTing quads in practice:
# fix up typo'ed predicates CONSTRUCT { GRAPH ?g { ?s rdf:type ?o } } WHERE { GRAPH ?g { ?s rdf:typo ?o } } # copy triples into a new graph CONSTRUCT { GRAPH ex:newGraph { ?s ?p ?o } } WHERE { ?s ?p ?o } # more complicated -- place constructed triples in # a new “inferred” graph and indicate this fact in # an Open Anzo metadata graph associated with the CONSTRUCT { GRAPH ex:inferredGraph { ?p ex:uncle ?uncle } GRAPH ?mdg { ?mdg anzo:hasInferredGraph true } } WHERE { GRAPH ?g { ?p ex:parent [ ex:brother ?uncle ] . } GRAPH ?mdg { ?mdg a anzo:metadatagraph ; anzo:namedGraph ?g } }
Of course, combine this with some of the other SPARQL extensions that Glitter supports—subqueries, projected expressions, assignment, and aggregates being my favorites—and you’ve got a powerful way to transform and extract quad-based RDF data.
Thanks Lee! Good stuff.