Query API
Release1.0.2
1.0.2
StatusSTABLE
STABLE
Date24 Apr 2021
24 Apr 2021
API Endpoint{baseUrl}/v1/query
{baseUrl}/v1/query
© 2003 - 2021 The openEHR Foundation | |
---|---|
The openEHR Foundation is an independent, non-profit foundation, facilitating the sharing of health records by consumers and clinicians via open specifications, clinical models and open platform implementations. | |
Licence | Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/ |
Support | Issues: Problem Reports Web: specifications.openEHR.org |
Amendment Record
Issue | Details | Raiser, Implementer | Completed |
---|---|---|---|
Release-1.0.2 | |||
4.1 | SPECITS-41: Add double quotes to ETag and If-Match headers | S Iancu | 21 Mar 2021 |
4.0 | SPECITS-47: Fix inconsistency over query_parameter(s) | P Pazos, S Iancu | 06 Mar 2021 |
Release-1.0.1 | |||
3.1 | SPECITS-37: Fix query definition endpoint and content-type errors | P Pazos, J Smolka, S Iancu | 01 Oct 2019 |
3.0 | SPECITS-32: Fix typos and minor documentary errors (fixes SPECPR-252, SPECPR-255) | E Sundvall, T Beale, S Iancu | 1 Sep 2019 |
2.2 | SPECITS-24: Added changelog | J Smolka, S Iancu | 12 May 2019 |
SPECITS-25, SPECITS-29: Change layout and structure | J Smolka, S Iancu | 12 May 2019 | |
SPECITS-30: Fix typos, links, examples and few other minor errors | S Iancu | 12 May 2019 | |
2.1 | Update links to new openEHR specifications website | S Iancu | 16 Dec 2018 |
Release-1.0.0 |
Requirements ¶
Purpose
This specification describes the service endpoints and data-models used when querying an openEHR system. The Archetype Query Language (AQL) is the primary query language.
Query types
Single EHR queries
A common use-case is to execute queries within a specific EHR.
This is achieved by supplying a ehr_id
query parameter or setting a openEHR-EHR-id
request header.
Population queries
Population queries are queries which are executed on several EHRs in the same request. Examples of use-cases can be:
-
Ward lists
-
Explore correlations between patients in a pandemic situation
-
Research, e.g. epidemiology, population health
Stored queries
Stored queries are queries which have their definition stored (registered) on the server. The queries will expose mandatory and optional parameters for the clients.
Using stored queries has lots of advantages:
-
separation of responsibilities (some users/developers write queries, others just call/execute them and consume the responses)
-
no need to pass long query string over the network
Stored queries are identified by name, used as qualified_query_name
,
and an optional version
number in SEMVER style (i.e. major.minor.patch
).
Usually a qualified_query_name
has a format like <namespace>::<query-name>
(e.g. org.openehr::compositions
).
If only a partial version
is supplied or version
is not supplied at all, the
system must use the latest version
with the supplied prefix - i.e. if only major
or major.minor
is used, then the latest query version with supplied prefix will be used.
Queries can be stored or, once stored, their definition can be retrieved using the definition endpoint.
Common Headers and Query Parameters ¶
All query execution requests SHOULD support at least the following parameters:
-
ehr_id
- used to execute the query within a single EHR context: an EHR identifier taken from EHR.ehr_id.value -
offset
- used for paging: the row number in result to start result-set from (0
-based); default0
-
fetch
- used for paging: the number of rows to fetch (i.e. limit); default depends on the implementation, but cannot be combined with AQL-top -
other parameter(s) to replace placeholder(s) within the query, here generically named
query_parameters
(see below).
Related request headers:
openEHR-EHR-id
- used to execute the query within a single EHR context: an EHR identifier taken from EHR.ehr_id.value
Related response headers:
ETag
- A unique identifier of the resultSet
About the ehr_id
parameter
This parameter SHOULD be supplied by clients when executing single EHR queries and MAY be used by the underlying backend to perform routing, optimizations or similar. It MUST NOT be supplied for ‘population queries’ and similar multi-patient queries.
Depending on the needs, clients MAY supply it as a query parameter ehr_id
or alternatively
as a request header named openEHR-EHR-id
.
Query parameters
Depending on each query definition, various query parameters SHOULD be supported, generically named query_parameters
in this specification, but in the real request they will have specific names (e.g. uid
, systolic_bp
, etc.)
according to their names in the query definition.
Provided query parameters SHOULD NOT be prefixed with $
sign. Instead, the server will (whenever necessary)
add the prefix or format queries as valid AQL queries.
As an example, for the following AQL query
SELECT c/name/value FROM COMPOSITION c WHERE c/uid/value = $uid
named as 'myQuery'
, the client can supply the uid
as a query parameter:
GET {baseUrl}/query/myQuery?uid=90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1
As another example, the request
GET {baseUrl}/query/com.vendor::compositions?temperature_from=36&temperature_unit=Cel
will pass query parameters temperature_from
and temperature_unit
to the underlying AQL query named com.vendor::compositions
.
See AQL-parameters specification for more details.
Request structure ¶
Below is a mostly self-documented AQL query request.
{
"q": "select o/data[at0002]/events[at0003 and name/value='Any event']/data[at0001]/items[at0004]/value/magnitude as temperature, o/data[at0002]/events[at0003 and name/value='Any event']/data[at0001]/items[at0004]/value/units as unit from EHR[ehr_id/value='554f896d-faca-4513-bddf-664541146308d'] CONTAINS Observation o[openEHR-EHR-OBSERVATION.body_temperature-zn.v1] WHERE o/data[at0002]/events[at0003 and name/value='Any event']/data[at0001]/items[at0004]/value/magnitude > $temperature and o/data[at0002]/events[at0003 and name/value='Any event']/data[at0001]/items[at0.63 and name/value='Symptoms']/value/defining_code/code_string=$chills order by temperature desc fetch 3",
"query_parameters": {
"temperature": 38.5,
"chills": "at0.64"
}
}
GET vs POST
Requests based on the GET
method have URI length restriction, or some characters might not be allowed and have to be encoded.
Long queries in the q
parameter and having a long list of query_parameters
may add up to reach that limit,
thus we recommend clients using the POST
method instead of GET
.
Response structure ¶
Metadata
Field | Description |
---|---|
_href |
URL of the query executed (only for GET endpoint) |
_type |
Defines type of the serialized object |
_schema_version |
The version of the specification defining the serialized object |
_created |
Result creation time (in the extended ISO 8601 format) |
_generator |
Some identifier of the application that generated the result. Useful i.e. for debugging |
_executed_aql |
The actual query (i.e. AQL) that was executed by the server after exploding the parameters. This attribute is not mandatory, but is useful for debugging |
Data
Field | Description |
---|---|
name |
Name of a query when registered as a stored query |
q |
The AQL which was given in the request |
columns |
Columns are defined by the client provided with the given AQL. I.e. select c/uid/value as CidValue, c/context/start_time as StartTime from .... will give two columns. One columns for CidValue and another for StartTime. |
columns.name |
Name of the column. I.e. CidValue or StartTime from the example above, when column alias is not present in the AQL a 0-based column index is used prefixed by a hash sign (i.e. #0 , #1 …) |
columns.path |
Path from the given AQL of the specified column. I.e. columns CidValue will have path /uid/value |
rows |
Ordered list with results. |
rows.row |
Each row list of cells. One cell for each column. Content of a cell is ANY (i.e. a OBJECT in most programming languages) |
ResultSet example
Below is a synthesized response with all attributes.
{
"meta": {
"_href": "... the URI for the executed AQL - used only for GET executions ...",
"_type": "RESULTSET",
"_schema_version": "1.0.0",
"_created": "2017-08-19T00:25:47.568+02:00",
"_generator": "DIPS.OpenEhr.ResultSets.Serialization.Json.ResultSetJsonWriter (5.0.0.0)",
"_executed_aql": "... the executed aql ..."
},
"name": "... the name or identifier of the stored query that was executed ...",
"q": "SELECT e/ehr_id/value, c/context/start_time/value as startTime, c/uid/value as cid, c/name FROM EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"columns": [
{
"name": "#0",
"path": "/ehr_id/value"
},
{
"name": "startTime",
"path": "/context/start_time/value"
},
{
"name": "cid",
"path": "/uid/value"
},
{
"name": "#3",
"path": "/name"
}
],
"rows": [
[
"81433066-c417-4813-9b29-79783e7bed23",
"2017-02-16T13:50:11.308+01:00",
"90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1",
{
"_type": "DV_TEXT",
"value": "Labs"
}
]
]
}
Query ¶
Actions upon resources of this group are also formally described in the I_QUERY_SERVICE Abstract Service Model interface.
200 OK
is returned when the server is able to execute the query.
Headers
Content-Type: application/json
ETag: "cdbb5db1-e466-4429-a9e5-bf80a54e120b"
Body
{
"meta": {
"_href": "... the URI for the executed AQL - used only for GET executions ...",
"_type": "RESULTSET",
"_schema_version": "1.0.0",
"_created": "2017-08-19T00:25:47.568+02:00",
"_generator": "DIPS.OpenEhr.ResultSets.Serialization.Json.ResultSetJsonWriter (5.0.0.0)",
"_executed_aql": "... the executed aql ..."
},
"name": "... the name or identifier of the stored query that was executed ...",
"q": "SELECT e/ehr_id/value, c/context/start_time/value as startTime, c/uid/value as cid, c/name FROM EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"columns": [
{
"name": "#0",
"path": "/ehr_id/value"
},
{
"name": "startTime",
"path": "/context/start_time/value"
},
{
"name": "cid",
"path": "/uid/value"
},
{
"name": "#3",
"path": "/name"
}
],
"rows": [
[
"81433066-c417-4813-9b29-79783e7bed23",
"2017-02-16T13:50:11.308+01:00",
"90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1",
{
"_type": "DV_TEXT",
"value": "Labs"
}
]
]
}
400 Bad Request
is returned when the server was unable to execute the query due to
invalid input, e.g. a request with missing q
parameter or an invalid query syntax.
408 Request Timeout
is returned when there is a query execution timeout
(i.e. maximum query execution time reached, therefore the server aborted the execution of the query).
Execute ad-hoc (non-stored) AQL queryGET/query/aql{?q,ehr_id,offset,fetch,query_parameters}
Execute ad-hoc query, supplied by q
parameter,
fetching fetch
numbers of rows from offset
and passing query_parameters
to the underlying query engine.
See also details on usage of query parameters.
- q
string
(required) Example: SELECT ... WHERE ...the AQL query to be executed
- ehr_id
string
(optional) Example: 7d44b88c-4199-4bad-97dc-d78268e01398an optional parameter to execute the query within an EHR context
- offset
number
(optional) Example: 10row number in result-set to start result-set from (
0
-based), default0
- fetch
number
(optional) Example: 10number of rows to fetch, default depends on the implementation
- query_parameters
string
(optional)query parameters (can appear multiple times)
Headers
Content-Type: application/json
Body
{
"q": "SELECT c FROM EHR e[ehr_id/value=$ehr_id] CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"offset": 0,
"fetch": 10,
"query_parameters": {
"ehr_id": "7d44b88c-4199-4bad-97dc-d78268e01398",
"systolic_bp": 140
}
}
200 OK
is returned when the server is able to execute the AQL query.
Headers
Content-Type: application/json
ETag: "cdbb5db1-e466-4429-a9e5-bf80a54e120b"
Body
{
"meta": {
"_href": "... the URI for the executed AQL - used only for GET executions ...",
"_type": "RESULTSET",
"_schema_version": "1.0.0",
"_created": "2017-08-19T00:25:47.568+02:00",
"_generator": "DIPS.OpenEhr.ResultSets.Serialization.Json.ResultSetJsonWriter (5.0.0.0)",
"_executed_aql": "... the executed aql ..."
},
"name": "... the name or identifier of the stored query that was executed ...",
"q": "SELECT e/ehr_id/value, c/context/start_time/value as startTime, c/uid/value as cid, c/name FROM EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"columns": [
{
"name": "#0",
"path": "/ehr_id/value"
},
{
"name": "startTime",
"path": "/context/start_time/value"
},
{
"name": "cid",
"path": "/uid/value"
},
{
"name": "#3",
"path": "/name"
}
],
"rows": [
[
"81433066-c417-4813-9b29-79783e7bed23",
"2017-02-16T13:50:11.308+01:00",
"90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1",
{
"_type": "DV_TEXT",
"value": "Labs"
}
]
]
}
400 Bad Request
is returned when the server was unable to execute the query due to
invalid input, e.g. a request with missing q
parameter or an invalid query syntax.
408 Request Timeout
is returned when there is a query execution timeout
(i.e. maximum query execution time reached, therefore the server aborted the execution of the query).
Execute ad-hoc (non-stored) AQL queryPOST/query/aql
Execute ad-hoc query, supplied by q
attribute,
fetching fetch
numbers of rows from offset
and passing query_parameters
to the underlying query engine.
See also details on usage of query parameters.
200 OK
is returned when the server is able to execute the query.
Headers
Content-Type: application/json
ETag: "cdbb5db1-e466-4429-a9e5-bf80a54e120b"
Body
{
"meta": {
"_href": "... the URI for the executed AQL - used only for GET executions ...",
"_type": "RESULTSET",
"_schema_version": "1.0.0",
"_created": "2017-08-19T00:25:47.568+02:00",
"_generator": "DIPS.OpenEhr.ResultSets.Serialization.Json.ResultSetJsonWriter (5.0.0.0)",
"_executed_aql": "... the executed aql ..."
},
"name": "... the name or identifier of the stored query that was executed ...",
"q": "SELECT e/ehr_id/value, c/context/start_time/value as startTime, c/uid/value as cid, c/name FROM EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"columns": [
{
"name": "#0",
"path": "/ehr_id/value"
},
{
"name": "startTime",
"path": "/context/start_time/value"
},
{
"name": "cid",
"path": "/uid/value"
},
{
"name": "#3",
"path": "/name"
}
],
"rows": [
[
"81433066-c417-4813-9b29-79783e7bed23",
"2017-02-16T13:50:11.308+01:00",
"90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1",
{
"_type": "DV_TEXT",
"value": "Labs"
}
]
]
}
400 Bad Request
is returned when the server was unable to execute the query due to
invalid input, e.g. at least one of the parameters has an invalid syntax.
404 Not Found
is returned when a query with qualified_query_name
and version
does not exist.
408 Request Timeout
is returned when there is a query execution timeout
(i.e. maximum query execution time reached, therefore the server aborted the execution of the query).
Execute stored queryGET/query/{qualified_query_name}/{version}{?ehr_id,offset,fetch,query_parameters}
Execute a stored query, identified by the supplied qualified_query_name
(at specified version
),
fetching fetch
numbers of rows from offset
and passing query_parameters
to the underlying query engine.
See also details on usage of query parameters.
Queries can be stored or, once stored, their definition can be retrieved using the definition endpoint.
- qualified_query_name
string
(required) Example: org.openehr::compositionsname of the query to be executed
- version
string
(optional) Example: 1.0query SEMVER version number
- ehr_id
string
(optional) Example: 7d44b88c-4199-4bad-97dc-d78268e01398an optional parameter to execute the query within an EHR context
- offset
number
(optional) Example: 10row number in result-set to start result-set from (
0
-based), default0
- fetch
number
(optional) Example: 10number of rows to fetch, default depends on the implementation
- query_parameters
string
(optional)query parameters (can appear multiple times)
Headers
Content-Type: application/json
Body
{
"offset": 0,
"fetch": 10,
"query_parameters": {
"ehr_id": "7d44b88c-4199-4bad-97dc-d78268e01398",
"systolic_bp": 140
}
}
200 OK
is returned when the server is able to execute the query.
Headers
Content-Type: application/json
ETag: "cdbb5db1-e466-4429-a9e5-bf80a54e120b"
Body
{
"meta": {
"_href": "... the URI for the executed AQL - used only for GET executions ...",
"_type": "RESULTSET",
"_schema_version": "1.0.0",
"_created": "2017-08-19T00:25:47.568+02:00",
"_generator": "DIPS.OpenEhr.ResultSets.Serialization.Json.ResultSetJsonWriter (5.0.0.0)",
"_executed_aql": "... the executed aql ..."
},
"name": "... the name or identifier of the stored query that was executed ...",
"q": "SELECT e/ehr_id/value, c/context/start_time/value as startTime, c/uid/value as cid, c/name FROM EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs[openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= $systolic_bp",
"columns": [
{
"name": "#0",
"path": "/ehr_id/value"
},
{
"name": "startTime",
"path": "/context/start_time/value"
},
{
"name": "cid",
"path": "/uid/value"
},
{
"name": "#3",
"path": "/name"
}
],
"rows": [
[
"81433066-c417-4813-9b29-79783e7bed23",
"2017-02-16T13:50:11.308+01:00",
"90910cf0-66a0-4382-b1f8-c0f27e81b42d::openEHRSys.example.com::1",
{
"_type": "DV_TEXT",
"value": "Labs"
}
]
]
}
400 Bad Request
is returned when the server was unable to execute the query due to
invalid input, e.g. at least one of the parameters has an invalid syntax.
404 Not Found
is returned when a query with qualified_query_name
and version
does not exist.
408 Request Timeout
is returned when there is a query execution timeout
(i.e. maximum query execution time reached, therefore the server aborted the execution of the query).
Execute stored queryPOST/query/{qualified_query_name}/{version}
Execute a stored query identified by the supplied qualified_query_name
(at specified version
).
See also details on usage of query parameters.
Queries can be stored or, once stored, their definition can be retrieved using the definition endpoint.
- qualified_query_name
string
(required) Example: org.openehr::compositionsname of the query to be executed
- version
string
(optional) Example: 1.0query SEMVER version number
Generated with aglio on 24 Apr 2021