-
Notifications
You must be signed in to change notification settings - Fork 0
Data Query Syntax
A data query is a request for a projection of the data in the dataset. The response from such a query is described in data query response. Requests are name/value pairs encoded as a single JSON object in a POST; the values themselves may be objects.
Any name whose name starts with @ is a reserved parameter
whose meaning is defined by this specification; other names
are the names of aspects used as part of value filtering.
-
"@sort":[{"PM": aspectName}, {"PM2": aspectName2}, ...]where PMi is@upor@down— the results of the query are sorted according to the values of the named aspects, leftmost first, in ascending order for@upand descending order for@down. If@sortis not specified or is empty, the results are in an arbitrary order which can change from response to response. A@sortmust have at least oneaspectName. -
"@limit": A,Aa non-negative integer — return at mostAresults, and as many as can be. (The results need not be sorted.) -
"@offset": B,Ba non-negative integer — the firstBresults are discarded. It is undefined behaviour if@offsetis present without@sort. -
"@itemLimit", "@itemOffset", "@itemSort", same as"@sort", "@limit", "@offset"but applied to the body of the sub-select rather than the entire query see generated SPARQL. -
@count : true, causes the query to count the number of matches and just return that count, not the matches themselves. The count is returned as a single result object of the form{ "@count" : 42 }. The value of the@countkey is ignored, if the key is present then a count query is run. The count query can be combined with@limitand@offsetparameters. In particular use of@limitsets an upper bound on the count. -
"@json_mode": S,Sis the string"complete"or the string"compact". Complete mode is equivalent having both"@suppress_types": trueand"@compact_optionals": true. The default vale is"complete". -
"@suppress_types": B,Btrue or false [default]; if true, non-XSD typed literals and URIs are represented by their string lexical form; otherwise literals are represnted as{"@value": lexicalForm, "@type": uriForType}. -
"@compact_optionals": B,Btrue or false [default]; if true, absent optionals are omitted from result rows and present optionals are represented by themselves; if false, absent optionals are represented by[]and present ones by[theValue]. -
"@search": S,Sa string — see below. -
"@lang": L— if present, string values with a language that's name does not start withLare discarded. ((Hmm, not right. Rethink.)) -
"@childof": R— if the dataset is a codelist dataset then this will return just those items which are direct children of the given root resource. Usenullas the root to list the top level children.
A filter is of the form "aspectName": range, requiring that the
value of the named aspect satisfies the given range. A range
is represented by a JSON object; keys of that object (typically one,
sometimes two) are the operators of that range and the value of
that key encodes the value anchor of the range.
-
"@eq": V—Vrepresents a value; the filter passes if the aspect value equalsV. Similarly,@ne,@le,@lt,@ge,@gt. -
"@oneof": [V1, V2 ...]— TheVirepresent values; the filter passes if the aspect value equals any of theVi. -
"@contains": V—Vmust be a string; the filter passes ifVis a substring of the aspect value. -
"@matches": X—Xmust be a single string, a array of two strings, or an object.If it is a single string, it must be a legal SPARQL regex, and the filter passes if
Vmatches it.If it is an array of two strings, the first must be a legal SPARQL regex and the second must be legal SPARQL regex flags. The filter passes if
Vmatches the regex given the flags.If it is an object, it must have exactly one of the properties
@valueor@case-insensitive-valuewith a string which is a legal SPARQL regex, and may have a property@flagswith a value which is legal SPARQL regex flags. The filter passes ifVmatches the given value with case-insensitivity enabled, ie, with the flagipresent. -
"@search": S— see Text Search below. -
"@below": R—Rmust be a resource naming a hierarchy root; this filter passes if the aspect value is at or below that root. -
"@in": R—Rmust be a resource naming a collection. ((More details of collections to be added later.)) This filter passes if the aspect value is a member of that collection. [Not yet implemented.]
The data query language allows representation of arbitrary RDF literals for the values of aspects.
-
number — plain JSON numeric value, making no special distinction between
int/decimal/float;17,10.66. -
boolean — plain JSON
trueorfalse. -
plain literal — plain JSON string value,
"hello","world". -
language-tagged literal — a JSON object with an
@valuemember bound to a string for the literal's lexical form and an@languagemember bound to a string for the literal's language code;{"@value: "chat", "@language": "fr"}. -
typed literals — a JSON object with an
@valuemember bound to a string for the literal's lexical form and an@typemember bound to a string for the URI of the literal's dadatype;{"@value": "false", "@type": "xsd:boolean"}. -
a resource — a JSON object with an
@idmember bound to a string for the resource's URI and an optional@labelmember bound to a string for the resource'srdfs:label; `{"@id": "http://epimorphics.com/public/vocabulary/games.ttl#players", "@label": "players"}. -
multiple values (such as the operands of
@oror@oneof) — a JSON array with the individual values as its elements;[17, "shortcake"].
Text search only works if the SPARQL endpoint for this data API supports the text query interface and a suitable index has been constructed.
// TODO put in a link to details of how to do that construction
An @search may appear outside an aspect (general) or within
it (local). A general search specifies text to be search for
for any literal of an item; a local search is restricted to the
values of an aspect. Within the search, values can optionally
have an associated indexing property.
-
"@search: "pattern"— search for items whose literal values matchpattern, which is a Lucene text pattern (details TOBESPECIFIED). -
"@search": {"@value": "pattern", "@property": "property"}— Search for items whose literal values forpropertymatchpattern. -
"@search": {"@value": "pattern", "@limit": N}— Search for items whose literal values matchpattern. Limit the number of results to less-than-or-equalN. This allows the default Lucene limit to be over-ridden. -
"@search": {"@value": "pattern", "@limit": N, "@property": "property"}— Search for items whose literal values forpropertymatchpattern, limiting the number of results toN.
A general search will generate a SPARQL query using the Fuseki-supported
text:query property. With no @property it generates the SPARQL fragment:
?item text:query "pattern"
With an @property:
?item text:query (property "pattern")
The kinds of query generated for an aspect-local @search
depend on the kind of value that the aspect has: literal
(datatype) values vs resource (object) values. If the
aspect's range type is literal, then it is those literal
values that are searched. If the aspect's range type is
a class, then it is the values of the properties of those
values that are searched.
An aspect with no range type is assumed to have non-literal values.
For a simple search, "aspectName": {"@search": "pattern"},
if the aspect is literal-valued then the SPARQL fragment
is:
?item text:query (aspectName "pattern")
ie, the search only considers items that have literal
values indexed under aspectName. If the aspect is
resource-valued then the generated query fragment is:
?aspectVar text:query "pattern"
where ?aspectVar is the variable bound to the values
of the aspect, ie, the search is over the literals
of the aspect values.
A compound @search that specifies an @property is
allowed only when the aspect has a non-literal range:
"aspectName": {"@search": {"@value": "pattern", "@property": "name"}}
generates the query fragment:
?aspectVar text:query (name "pattern")
All the aspect filters of a query are implicitly ANDed together
to select the returned subset of the dataset queried over. It's
possible to use @not, @or, and @and to produce composite
queries.
Below, A, B, ... must each be aspect filters as described
above, or further (nested) boolean compositions.
If a query has a member "@not": [A, B ...], the query will
reject any results which make A and B and ... all true.
{"pf:A": {"@lt": 17}, "@not": [{"pf:B": {"@ge": 22}}]}
pf:A must have a value less than 17, and pf:B must have
a value less than 22. (In this case it's also possible to
change @ge to @lt and pull the pf:B constraint to the
top level assuming pf:B isn't optional. An optional aspect
can satisfy (not A=V) by having no value rather than by
having a value not equal to V.)
If a query has a member "@or": [A, B, ...], the query will accept
any results which make any of A, B, ... true, even if the
implicitly ANDed filters would reject them.
{"pf:A": {"@lt": 17}, "@or": [{"pf:B": {"@ge": 22}}]}
pf:A must have value less than 17 or pf:B must have value
at least 22.
If a query has a member "@and": [A, B, ...], then the query
will reject any results for which any of A, B, ... is false.
Normally you don't need to write an @and, because everything
is ANDed together anyway, but it's useful when nesting composites.
"pf:postcode": {"@eq": "BC4"},
"@and:" ["@or":
[ {"pf:class": {"@eq": "ClassA"}}
, {"pf:class": {"@eq": "ClassB"}}
]]
The pf:postcode must be "EC4" and the pf:class must be
"ClassA" or "ClassB".
(If the @and is dropped, then the query would mean "postcode
muse be EC4 or class is ClassA or class is ClassB", a quite
different query.)
(@oneof is the idiomatic tool to use for this query.)