Ditto utilizes a subset of RQL as language for specifying queries.
The RQL project page says about it:
Resource Query Language (RQL) is a query language designed for use in URIs with object style data structures. […]
RQL can be thought as basically a set of nestable named operators which each have a set of arguments. RQL is designed to have an extremely simple, but extensible grammar that can be written in a URL friendly query string.
An example helps more than a thousand words, so that would be the example of a simple RQL query querying
for foo="ditto" and bar<10:
and(eq(foo,"ditto"),lt(bar,10))
That query consists of one logical operator “and”, two relational operators of which each consists of a property and a value.
The following sections describe what the RQL syntax is capable of and which RQL operators are supported in Eclipse Ditto.
eq(foo,3), is supported by Eclipse Ditto and that Ditto added more non-specified operators, e.g.
like and exists.RQL filter
The RQL filter specifies “what” to filter.
Query property
<property> = url-encoded-string
When not starting with a prefix <some-prefix>:, the RQL query property specifies a field in the JSON representation
of a Thing.
For example a query property thingId selects the Thing ID as property, a query property attributes/location selects
an attribute with the name location as query property.
To filter nested properties, Ditto uses the JSON Pointer notation (RFC-6901),
where the property can also start with a slash / or omit it, so those 2 query properties are semantically the same:
/attributes/locationattributes/location
The following example shows how to apply a filter for the sub property location of the parent property attributes
with a forward slash as separator:
eq(attributes/location,"kitchen")
Placeholders as query properties
When using an RQL expression in order to e.g. filter for certain change notifications, the query property might be a placeholder instead of a field in JSON representation inside the Thing.
Currently supported placeholders for RQL expressions are:
topic:<placeholder-name>resource:<placeholder-name>time:<placeholder-name>
The placeholder documentation describes which placeholder names are supported.
Query value
<value> = <number>, <string>, <placeholder>, true, false, null
<number> = <double>, <integer>
<string> = "url-encoded-string", 'url-encoded-string'
<placeholder> = time:now, time:now_epoch_millis
String values may either be delimited using single or double quotes.
Comparison of string values
gt, ge, lt and le, do not support a special
“semantics” of string comparison (e.g. regarding alphabetical or lexicographical ordering).However, you can rely on the alphabetical sorting of strings with the same length (e.g. “aaa” < “zzz”) and that the order stays the same over multiple/different filter requests.
Comparison of other data types
Relational operators
The following relational operators are supported.
eq
Filter property values equal to <value>.
eq(<property>,<value>)
Example - filter things owned by “SID123”
eq(attributes/owner,"SID123")
ne
Filter property values not equal to <value>.
ne(<property>,<value>)
Example - filter things with owner different than “SID123”
ne(attributes/owner,"SID123")
The response will contain only things which do provide an owner attribute (in this case with value 0 or not SID123).
gt
Filter property values greater than a <value>.
gt(<property>,<value>)
Example - filter things with thing ID greater than “A000”
gt(thingId,"A000")
ge
Filter property values greater than or equal to a <value>.
ge(<property>,<value>)
Example - filter things with thing ID “A000” or greater
ge(thingId,"A000")
lt
Filter property values less than a <value>.
lt(<property>,<value>)
Example - filter things with thing ID lower than “A000”
lt(thingId,"A000")
le
Filter property values less than or equal to a <value>.
le(<property>,<value>)
Example - filter things with thing ID “A000” or lower
le(thingId,"A000")
in
Filter property values which contains at least one of the listed <value>s.
in(<property>,<value>,<value>, ...)
Example - filter things with thing ID “A000” or “AB00” or “AZ99”
in(thingId,"A000","AB00","AZ99")
like
Filter property values which are like (similar) a <value>.
like(<property>,<value>)
like operator is not defined in the linked RQL grammar, it is a Ditto
specific operator.Details concerning the like-operator
The like operator provides some regular expression capabilities for pattern matching Strings.
The following expressions are supported:
- *endswith => match at the end of a specific String.
- startswith* => match at the beginning of a specific String.
- *contains* => match if contains a specific String.
- Th?ng => match for a wildcard character.
Examples
like(attributes/key1,"*known-chars-at-end")
like(attributes/key1,"known-chars-at-start*")
like(attributes/key1,"*known-chars-in-between*")
like(attributes/key1,"just-som?-char?-unkn?wn")
ilike
Filter property values which are like (similar) and case insensitive <value>.
ilike(<property>,<value>)
ilike operator is not defined in the linked RQL grammar, it is a Ditto
specific operator.Details concerning the ilike-operator
The ilike operator provides some regular expression capabilities for pattern matching Strings with case insensitivity.
The following expressions are supported:
- *endswith => match at the end of a specific String.
- startswith* => match at the beginning of a specific String.
- *contains* => match if contains a specific String.
- Th?ng => match for a wildcard character.
Examples
ilike(attributes/key1,"*known-CHARS-at-end")
ilike(attributes/key1,"known-chars-AT-start*")
ilike(attributes/key1,"*KNOWN-CHARS-IN-BETWEEN*")
ilike(attributes/key1,"just-som?-char?-unkn?wn")
exists
Filter property values which exist.
exists(<property>)
exists operator is not defined in the linked RQL grammar, it is a Ditto
specific operator.Example - filter things which have a feature with ID “feature_1”
exists(features/feature_1)
Example - filter lamps which are located in the “living-room”
and(exists(features/lamp),eq(attributes/location,"living-room"))
Logical operators
and
Ensure that all given queries match.
and(<query>,<query>, ...)
Example - filter things which are located on the “upper floor” in the “living-room”
and(eq(attributes/floor,"upper floor"),eq(attributes/location,"living-room"))
or
At least one of the given queries match.
or(<query>,<query>, ...)
Example - filter all things located on the “upper floor”, and all things with location “living-room”
or(eq(attributes/floor,"upper floor"),eq(attributes/location,"living-room"))
not
Negates the given query.
not(<query>)
Example - filter things whose ID do not start with a common prefix
not(like(thingId,"org.eclipse.ditto:blocked*"))
RQL sorting
The RQL sorting part specifies in which order the result should be returned.
sort(<+|-><property>,<+|-><property>,...)
- Use + for an ascending sort order (URL encoded character %2B)
- Use - for a descending sort order (URL encoded character %2D)
Example - sort the list ascending by the thing ID
sort(+thingId)
Example - sort the list ascending by an attribute
sort(+attributes/location)
Example - multiple sort options
sort(-attributes/location,+thingId)
This expression will sort the list descending by location attribute.
In case there are multiple things with the same location attribute, these are sorted ascending by their ID.