Initial Release
This project is a functional example of an openEHR-style clinical data repository built on InterSystems IRIS.
It demonstrates how to store compositions as JSON, validate them with the Archie library, and query them using an AQL→SQL transformer based on JSON_TABLE.
The repository uses a hybrid strategy:
OPENEHR_Object.Composition) accelerates querying by storing metadata extracted from the JSON.JSON_TABLE to project only the AQL-requested parts of a composition.This preserves openEHR semantics while enabling efficient relational querying.
All compositions are persisted as full JSON documents, including all openEHR RM structures such as:
The storage table typically contains:
| Column | Description |
|---|---|
doc |
Raw openEHR JSON |
ehrId |
EHR identifier |
compositionUid |
Composition UID |
| Metadata | Timestamps, etc. |
Deep JSON values are resolved at query time using SQL functions — no schema flattening is required.
A helper table stores selected metadata extracted from each composition JSON:
This enables:
JSON parsing occurs only when projecting fields into JSON_TABLE.
The project integrates the Archie Java library to validate compositions before storing them.
Archie provides:
This ensures the repository behaves similarly to production-grade openEHR CDR systems.
The method OPENEHR.Utils.AuxilaryFunctions.Transform converts AQL queries into IRIS SQL queries.
It supports:
The generated SQL uses JSON_TABLE to dynamically extract JSON fragments into relational columns.
Each COMPOSITION archetype has a CSV file defining the JSON base paths for all contained archetypes.
Example schema:
composition,archetype_id,json_path
openEHR-EHR-COMPOSITION.encounter.v1,openEHR-EHR-OBSERVATION.blood_pressure.v2,$.content[]?(@…)
openEHR-EHR-COMPOSITION.encounter.v1,openEHR-EHR-CLUSTER.laboratory_test_analyte.v1,$.content[]?(@…).data.items[*]?(@…)
The transformer:
Each matching CSV produces a JSON_TABLE SELECT.
For each AQL expression such as:
m/data[at0001]/items[at0002]/value/value AS medication_text
The transformer builds a relative JSON path:
$.data[]?(@.archetype_node_id==“at0001”).items[]?(@.archetype_node_id==“at0002”).value.value
This becomes part of a JSON_TABLE definition:
JSON_TABLE(c.doc, ‘’ COLUMNS (medication_text VARCHAR(4000) PATH ‘$.data[*]?(@…)’))
The transformer converts AQL MATCHES expressions into SQL:
| AQL Expression | SQL Output |
|---|---|
'.*text.*' |
col LIKE '%text%' |
{'.*(A|B).*'} |
(col LIKE '%A%' OR col LIKE '%B%') |
{'.*A.*','.*B.*'} |
(col LIKE '%A%' OR col LIKE '%B%') |
{|120..140|} |
col BETWEEN 120 AND 140 |
{|<100|} |
col < 100 |
{|>160|} |
col > 160 |
This makes the AQL semantics fully compatible with SQL WHERE clauses.
The transformer detects when the SELECT includes:
COUNT(...)COUNT(DISTINCT ...)DISTINCT keywordsIt rewrites the outer SQL to ensure:
This allows AQL aggregate queries to behave as expected.
If the AQL does not specify a COMPOSITION archetype:
UNION ALL
This allows querying multiple composition types in a single AQL.
To avoid SQL keyword conflicts:
| AQL alias | SQL alias |
|---|---|
time |
time_value |
date |
date_value |
Both SELECT and ORDER BY clauses are rewritten accordingly.
Build the image wich we are going to use during the workshop:
$ git clone https://github.com/intersystems-ib/workshop-openehr
$ cd workshop-openehr
$ docker-compose build
docker-compose up -d
Automatically an IRIS instance will be configured and deployed.
Open the Management Portal.
Login using the default superuser/ SYS account.
Import OPENEHR.postman_collection.json into your local POSTMAN.

You can test the openEHR repository following these steps:


This project provides:
It demonstrates how openEHR principles, JSON-native indexing, and SQL analytics can coexist to form a powerful and extensible Clinical Data Repository (CDR).