Resource Query Language (RQL)

RQL, or Resource Query Language, is a query language used for querying and manipulating resources through the URI. RQL provides the ability to filter, sort, paginate, and project data. It is straightforward to use, yet it offers flexibility to address complex scenarios.

For applications written in JavaScript or TypeScript, we highly recommend using our SDK to build RQL queries.

Using RQL

RQL is composed of a set of operators. These operators can be broadly classified into three categories:

  • Comparison Operators: These operators perform comparison operators, such as equals, greater than, etc.

  • Logical Operators: Used to combine multiple conditions

  • Algorithmic Operators: These operators pertain to functionalities like sorting and pagination.

Operators are represented in the format operator(arg1,arg2,...). Everything can be expressed as a set of such operators by means of nesting .

Practical Examples

Lets say you want to host a web page that features a table listing all users of a specific medical device application. Implementing filtering is crucial. This is where RQL enter the picture.

Try It Yourself

You can test the following examples in real-time by going to Extra Horizon's Control Center. Our Control Center offers a user table for your medical device application that supports RQL queries.


Basic Filtering

To display users with the first name "Adam" in the table, your GET request would look like:

GET /users/v1/?eq(first_name,Adam)

Sorting

To sort users based on their creation timestamp:

GET /users/v1/?sort(creation_timestamp)

Pagination

To paginate your results with a limit of 10 users and to retrieve the third page:

GET /users/v1/?limit(10,20)
  • First parameter 10 expresses the number of users to return

  • Second parameter 20 offsets the starting position in the result set. The first 20 users will be skipped.

Projection

To request only specific fields such as first_name, last_name, and creation_timestamp:

GET /users/v1/?select(first_name,last_name,creation_timestamp)

Combining Operators

Logical operators can be used to combine multiple operators. For example, to filter users with first name "Adam" and last name "Smith":

GET /users/v1/?and(eq(first_name,Adam),eq(last_name,Smith))

Algorithmic operators can be added in the same fashion:

GET /users/v1/?and(eq(first_name,Adam),select(first_name))

Operators

FunctionNote

or(<condition>,<condition>,...)

Returns records that satisfy at least one of the specified conditions.

and(<expression>,<expression>,...)

Returns records that satisfy all specified conditions. In addition to combining conditions, this operator can be used to combine algorithmic operators.

eq(<property>,<value>)

Filters records where <property> exactly matches <value>. If <property> is an array, it must contain <value>.

Note: Object comparisons are not supported.

ne(<property>,<value>)

Filters records where <property> does not match <value>. If <property> is an array, it should not contain <value>. Note: Object comparisons are not supported.

gt(<property>,<value>)

Filters records where <property> is greater than <value>.

ge(<property>,<value>)

Filters records where <property> is greater than or equal to <value>.

lt(<property>,<value>)

Filters records where <property> is less than <value>.

le(<property>,<value>)

Filters records where <property> is less than or equal to <value>.

in(<property>,<value>,<value>,...)

Filters records where <property> matches any of the listed values. If <property> is an array, only one element needs to match.

out(<property>,<value>,<value>,...)

Filters records where <property> matches none of the listed values. If <property> is an array, no element can match any of the listed <value>s.

contains(<property>) contains(<property>,<condition>)

Filters records where <property>, assumed to be an array of objects, contains at least one object that satisfies <condition>. When <condition> is not provided, objects which contain <property> are returned.

excludes(<property>) excludes(<property>,<condition>)

Filters records where <property>, assumed to be an array of objects, does not contain any object that satisfies <condition>. When <condition> is not provided, objects which do not have <property> are returned.

like(<property>,<value>)

Filters records where <property> contains <value> as a substring. This applies to strings or arrays of strings. Unsupported data types will yield no records.

limit(<limit>,<offset>)

Limits the number of returned records and optionally offsets the starting position in the result set.

  • limit(1) returns only 1 record:

  • limit(2,0) returns the two resources in positions 0 and 1

  • limit(10) returns up to 10 resources starting from position 0

  • limit(2,2) returns the two resources in positions 2 and 3

sort(<property>) sort(-<property>)

Sorts the returned records by <property>. Ascending sort is the default. For descending order, prepend - to <property>.

select(<property>,<property>,...)

Trims the returned records to only include the specified properties.

skipCount()

skip_count()

Skips the record counting step of a request to increase performance. As a result, the page object in a response will not include the total field.

Limitations

Every tool has its constraints, and RQL is no exception. Understanding these limitations helps you use RQL more effectively.

Double Encoding of Special Characters

Imagine a scenario where you need to filter records based on a description that includes the string a)a:

GET /data/v1/?like(description,a)a)

Executing the above query without any modifications results in an INVALID_RQL_EXCEPTION. The problem lies with the special character ). RQL can't discern whether the ) marks the end of the argument list or is part of the string value a)a.

You might think of solving this by URL encoding the special character ) as %29:

GET /data/v1/?like(description,a%29a)

Unfortunately, this approach still triggers an INVALID_RQL_EXCEPTION. The reason lies in RQL's automatic decoding of incoming requests, a design choice to accommodate HTTP clients that perform automatic URL encoding. Consequently the encoded %29 gets decoded back to ), leaving us with the initial problem.

To effectively handle special characters, RQL mandates double encoding for such string values. This means that the special character should be encoded twice. Here's how you would apply double encoding to the initial query:

GET /data/v1/?like(description,a%2529a)

It is highly recommended to use our SDK if you are building a JavaScript or Typescript application. Our SDK will automatically double encode string values.

Double encoding is not limited to parentheses. RQL requires all special characters to be double encoded:

  • Simple symbols like /, (, ], ".

  • Accents such as é, à, ö.

  • Whitespace characters including spaces, newlines, and tabs.

Services with the skip count RQL operator

The skip count RQL operator is currently supported in select services, and efforts are underway to make it available for all services in the near future. Attempting to use the skip count on a service that does not yet support it may result in an INVALID_RQL_EXCEPTION.

Services currently supporting the skip count operator:

  • Data Service

  • Events Service

  • Profiles Service

  • Tasks Service

  • Users Service

  • Notification Service

Last updated