$Id: N3QL.html,v 1.66 2004/07/03 13:33:38 timbl Exp $
N3QL is an implementation of an N3-based query language for RDF. It treats RDF as data and provides query with triple patterns and constraints over a single RDF model. The target usage is for scripting and for experimentation in information modelling languages. The language is derived from Notation3.and RDQL.
This paper is designed to be comparable with the RDQL paper. However it also describes the format for returned data, as the other part fo the data access protocol.
The purpose of N3QL is as a model-level access mechanism that is higher level than an RDF API. Query provides one way in which the programmer can write a more declarative statement of what is wanted, and have the system retrieve it.
N3QL is an application of Notation3. Like N3Rules, it is a constrained subset of N3 Full.
See:
N3QL is constrained in that:
N3QL is simply N3 which uses specific properties to convey the import of a query and its response. These properties are in the N3QL namespace, <http://www.w3.org/2004/ql>.
select
where
graph.
where
select
graph.
[] select { result is (?x ?y) }; where { ?x a ex:Librarian; ex:hairColor ?y }. _____________________________________________________ result is ( ex:Joe "black"), (ex:Mary, "red").
A query service, on receiving a message under this protocol,
finds all things which are the subject of a
"where
" property. Each of these is deemed to be
a Query. For each query, it finds every combination of
bindings for the variables in the where
graph
which unify that graph with the service's knowledge base
(stored or virtual). It then determines from that set the set
of distinct bindings of the set of variables which also occur
in the select graph. For each set of bindings, it creates a
result graph by substituion of the bindings into the
select
graph.
The result graphs are merged and the resulting graph is the response to the query. Advantage: simpler. The result is a single RDF graph. The query client can simply find the tuples returned.
Example:
result is ( ex:Joe "black"), (ex:Mary, "red").
The query is expressed in N3 ideally without a lot of extra whitespace, and then is URL-encoded and appended to the service's URI with an intervening "?" character. The result of dereferencing the URI so formed is the return of a representation in N3 (unless content -negotiated otherwise) of the response message.
TBD
The use of N3 makes the query language very extensible.
Extensions to the query message may be added in that extra properties, in any namespace, can be added to the query. This is extra information. The service is not required to understand such extra information, and is not bound to take it into consideration. Clients cannot add extra information which attempts to changes the meaning of the query, unless there is a prior agreement between the parties.
Similary, servers may add extra information to the response if the response is in the second form.
In order to extend the query language in such a way that a service must understand the extension, the select and/or where properties are replaced by different ones, for example ones form a enw namespace. This means that existing older clients will not be able to find a query, and will have to return an error.
A query service is a service, which may be described using RDF. The ability of a service to support specific built-in functions may for example be a good thing to advertize in a service description.
A query could be labelled within the request message as requiring specific functionality,
The result message is the response graph encoded, typcially, in N3. (Where HTTP GET is used, format negotiation could be used to negotiate something else).
This is a straw proposal which, while functional, really demonstrates how a query langauge is simple constructed using N3. The Data Access Working Group in designing such a langauge can of course change and add vocabulary.
A number of design options have been given.
Every query could have the default namespace (empty prefix) set up to be
Also, there could be prefixes assumed for the namespaces above even when they are not the empty prefix. For example, "q:" for the query language and "s:" for the service local namespace makes sense.
This query langauge uses the N3 formula extensions, in the sense that graphs are extended to allow nested graphs and variables. However, the N3 syntax does not have to be used. If an XML syntax is desired, an extended form of the RDF/XML syntax could be created to be completely equivalent to the N3 syntax.
For example, the first example above could be represented as shown in the appendix.
Assuming the declarations (which could be an assumption on the protocol)
@prefix : <http://www.w3.org/2004/ql#>. @keywords a, is.
Query example 1: Retrieve the value of a known property of a known resource
<> select { ?x a result} where { <http://somewhere/res1> <http://somewhere/pred1> ?x }. ______________________________________________ <http://somewhere/pred1>a result.
Query example 2: constraints (option a)
<> select { Result is (?a ?b)}; where { ?a <http://somewhere/pred1> ?b; ?b math:lessThan 5}. __________________________________________________ Result is ( "blue" 2), ("red" 1), ("purple", -16)
Query example 2: constraints (option b)
<> select { (?a ?b) a Result}; where { ?a <http://somewhere/pred1> ?b}; and { ?b math:lessThan 5}. __________________________________________________ Result is ( "blue" 2), ("red" 1), ("purple", -16)
Query example 3: paths in the graph
<> select { (?a ?b) a Result}; where { ?a <http://somewhere/pred1> [<http://somewhere/pred2> ?b]}.
compare RDQL:
SELECT ?a, ?b
WHERE (?a, <http://somewhere/pred1>, ?c) ,
(?c,
<http://somewhere/pred2>, ?b)
<> select { Result is (?x ?y); where { ?x list:in ?x. ?y ex:memberList ?z }. __________________________________________ Result is ( ex:joe ex:mathClub), (ex:joe ex:skiClub); (ex:Mary ex:skiClub).
These design possibilities are not part of the current language as defined here. They are there to show that the issues are acknowledged, and to show that solution to these issues are possible. The primary purpose of this specifciation at this current state is to show that a query language and easily be built using N3. It would be unwise to reject the syntax because this document did not provide a feature which the work group felt was essential. That said, addition of additonal features would in most cases make the language unnecessaily complicated for a version 1.0.
Include the following property of a query or not?:
where
graph. The query service binds the
largest of subset of the union of where
and
option
graphs which it can. This is not a
well-defined operation right now, and it is not clear that
it should be a requirement for every query service, or
clear that it should be included in N3QL at all. This
requires some sort of way of returning variable amounts of
data. One way would be to make the select graph such that a
subset could be returned by binding only those variables
which had bindings.
option
:q1 q:select { ex:result ex:is [ex:main(?x ?y); ex:phone ?p] }; q:where { ?x a ex:Librarian; ?x ex:hairColor ?y }; q:option { ?x ex:phone ?p}. _____________________________________ ex:result ex:is [ex:main ( ex:Joe "black"); ex:phone "+1-234-555-6789"], [ex:main (ex:Mary, "red")].
Include the following property of a query? (No)
and
and
clause is like the where
clause but contains constrains whcih are calculated rather
than searched for. The name is from the AND clause in RDQL.
<> select { ?p ex:had ?t}; where { [ a ex:Reading; ex:temp ?t; ex:place ?p]. ?t math:greaterThan 25 }. ___________________________________________ ex:London ex:had 26. ex:Barcelona had 31.
<> select { ?p ex:had ?t }; where { [ a ex:Reading; ex:temp ?t; ex:place ?p]}; and { ?t math:greaterThan 25 }. ___________________________________________ ex:London ex:had 26. ex:Barcelona had 31.
Some people seem to think that calculations should be clearly separated from knowledge base searches.
There is no distinct line between "calculation" and "search"
especialy when one extends the "search" to include inference,
and "calculation" to allow querying of the web, and the use
of functions which may invoke in turn search and inference.
It is short-sighted to make this distinction when in fact an
implementation can easily triage the tuples into builtins and
non-builtins. To make this more resilient, see the
requirement
property and the discussion.
Include the following optional property? (No)
Include the following property of a query? (No)
Use the following alternative from of response message? (No)
<mid:2314@ex.com> q:result { result is (ex:Joe "black")}, { result is (ex:Mary, "red")}; svc:responseTime 0.0023 .
The only awkwardness in the syntax above could be the select clause, in cases in which a list of variables is to be returned. The reason for this is that the selct clause has to be a graph, in order to be quoted. It is logically incorrect to give the variables unquoted. N3 has no syntax (such as backquote syntax) for explicitly quoting the name of a variable, and as variables are in fact URIs to give their string values is messy. Two ways this could be changed would be as follows.
One option would be to add variable name quoting to N3, like:
:q1 q:select `x`, `y`; q:where { ?x a ex:Librarian, ex:hairColor ?y}.
A second option would be to add to N3 a special keyword specially for selct clauses, which would be new syntax (a little comparable with @forAll) which implies quoting, something like:
:q1 @select ?x, ?y; q:where { ?x a ex:Librarian, ex:hairColor ?y}.
Neither of these add a lot, and both complicate the N3 language itself.
The query langauge is quite similar to a rule language. If
rather than [] select F; where
G
one writes G =>
F,
then one has a rule foo.n3 which can then
be run on a knowledge base with
cwm kb1.n3 --filter=rule.n3.
An alternative form of the query language, if the option and and clauses are not used, would be to use log:implies, shorthand =>, instead. This would be even more compact for small queries.
{?x a ex:Librarian; ex:hairColor ?y} => {result is (?x ?y)};. _____________________________________________________ result is ( ex:Joe "black"), (ex:Mary, "red").
The query
[] select { result is (?x ?y) }; where { ?x a ex:Librarian; ex:hairColor ?y }. _____________________________________________________ result is ( ex:Joe "black"), (ex:Mary, "red").
could be represented in XML, by extending the RDF/XML 1.0 syntax, for example as
<rdf:RDF xmlns="http://www.w3.org/2004/ql#" xmlns:ex="http://www.example.com/foo#" xmlns:q="http://www.w3.org/2004/ql#" xmlns:rdf="http://www.example.org/rdf2#" rdf:forAll="#x #y"> <rdf:Description> <select rdf:parseType="Quote"> <rdf:Description rdf:about="http://www.w3.org/2004/ql#result"> <is rdf:parseType="Resource"> <rdf:first rdf:resource="#x"/> <rdf:rest rdf:parseType="Resource"> <rdf:first rdf:resource="#y"/> <rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/> </rdf:rest> </is> </rdf:Description> </select> <where rdf:parseType="Quote"> <ex:Librarian rdf:about="#x"> <ex:hairColor rdf:resource="#y"/> </ex:Librarian> </where> </rdf:Description> </rdf:RDF>
Note that this is NOT RDF 1.0, as the RDF spec specifically disallows such extensions.
It can also be represented as an RDF graph using a form of reification, for example:
@prefix : <http://www.w3.org/2004/06/rei#> . @prefix owl: <http://www.w3.org/2002/07/owl#> . @prefix t: <#> . [ :existentials [owl:oneOf () ]; :statements [ owl:oneOf ( [ :object [ :existentials [ owl:oneOf () ]; :statements [ owl:oneOf ( [ :object [ :items ( [:uri "http://www.w3.org/2000/10/swap/test/ql/t00.n3#x" ] [:uri "http://www.w3.org/2000/10/swap/test/ql/t00.n3#y" ] ) ]; :predicate [ :uri "http://www.w3.org/2004/ql#is" ]; :subject [ :uri "http://www.w3.org/2004/ql#result" ] ] ) ]; :universals [owl:oneOf () ] ]; :predicate [:uri "http://www.w3.org/2004/ql#select" ]; :subject _:a ] [ :object [ :existentials [owl:oneOf () ]; :statements [ owl:oneOf ( [ :object [:uri "http://www.example.com/foo#Librarian" ]; :predicate [:uri "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" ]; :subject [:uri "http://www.w3.org/2000/10/swap/test/ql/t00.n3#x" ] ] [ :object [:uri "http://www.w3.org/2000/10/swap/test/ql/t00.n3#y" ]; :predicate [:uri "http://www.example.com/foo#hairColor" ]; :subject [:uri "http://www.w3.org/2000/10/swap/test/ql/t00.n3#x" ] ] ) ]; :universals [owl:oneOf () ] ]; :predicate [:uri "http://www.w3.org/2004/ql#where" ]; :subject _:a ] ) ]; :universals [ owl:oneOf ( "http://www.w3.org/2000/10/swap/test/ql/t00.n3#x" "http://www.w3.org/2000/10/swap/test/ql/t00.n3#y" ) ] ]. #ENDSfor the record.