EHRbase入門3 - AQL

# はじめに
第3回目はAQL(Archetype Query Language)を使ってEHRbaseに対してクエリーを発行します。
* AQLとはなにか
* 文法概要
* サンプル
* EHRbaseのAQL API
* 書き方
* 参考資料

---

# AQLとはなにか

Archetype Query Languageの略で、SQLに似た文法でEHRに対して統一的に問い合わせ(query)を発行することができます.

統一されたQueryインターフェースがあるので、システムに依存することなくアプリケーションを開発することができます。

現在の実装は[ANTLR](https://www.antlr.org/)をベースに行われていて、言語による差がなく広まっています。AQLを使いこなすことがopenEHR活用の鍵です。

---
# 文法概要

AQLはSQLに似ています。SELECT, FROM, WHERE, ASはほぼ同じ意味を持ちます。重要なのはパスです。Archetypeのパスの考え方については[こちら](https://trac.openehr.jp/wiki/Archtectural%20Overview%20Paths)をご覧ください。

* SELECT: 取得する項目を指定します。
* FROM: 取得する対象を指定します
* WHERE: 取得する条件を指定します
* AS: 別名を指定します。

---
# サンプル

```
SELECT c/context/start_time/value, obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude
FROM COMPOSITION c CONTAINS OBSERVATION obs [openEHR-EHR-OBSERVATION.temperature.v1] 
WHERE obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude >= 38.0
```

---
# EHRbaseのAQL API
* GET, POSTともに準備されています。
* GET
```
GET /rest/openehr/v1/query/aql
```

パラメータ

| key| value |
|:-:|:-:|
| q | AQL文  |
| fetch| 取得するデータの数を指定|



* POST
```
POST /rest/openehr/v1/query/aql
```

Bodyにqをキーとして値にAQLを書いたJSONを

| key| value |
|:-:|:-:|
| q | AQL文  |

* 結果

| key| value |
|:-:|:-:|
| q | AQL文  |
|columns|データのパスとデータ列の順番|
|rows|データ本体|

---
# 書き方
AQLはFROM, WHERE, SELECTの順に書いていくとわかりやすいです。

1. FROMでデータ取得の対象を指定します。
2. WHEREで条件を指定します。
3. 最後にSELECTで取得する項目を指定します。

「38度以上の発熱がある患者のEHR IDと、発熱時の症状も取得する」ことを例にとって解説します。
サンプルデータは以下のソースコードで rais db:seed を行ってランダムに作成したものを使います。

https://github.com/skoba/rails-ehrbase

---
# FROM

「38度以上の発熱がある患者のEHR IDと、発熱時の症状も取得する」には以下のようなデータセットが含まれると考えます。

 * EHRの中で体温が記録されているアーキタイプ(openEHR-EHR-OBSERVATION.temperature.v1)を含むCOMPOSITION。
 * 上記のCOMPOSITIONを含むEHR

AQLで記述するとこうなります。

```
FROM EHR e CONTAINS COMPOSITION c 
CONTAINS OBSERVATION obs [openEHR-EHR-OBSERVATION.temperature.v1]
```

---
# WHERE

「38度以上の発熱がある患者のEHR IDと、発熱時の症状も取得する」は以下のような条件であると考えます。

* 体温を示すarchetype(openEHR-EHR-OBSERVATION.temperature.v1)の値を示すパス（/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude）が38.0以上であること

AQLで記述するとこうなります。

```
WHERE obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude >= 38.0"
```
---
# SELECT

「38度以上の発熱がある患者のEHR IDと、発熱時の症状も取得する」で取得すべきは以下の項目です。

* 体温を示すアーキタイプのパス
* EHRのehr_id
* 症状を示すアーキタイプのパス

SELECT文で指定すると以下のようになります。

```
SELECT e/ehr_id/value,
 obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude,
 c/content[openEHR-EHR-OBSERVATION.story.v1]/data[at0001]/events[at0002]/data[at0003]/items[openEHR-EHR-CLUSTER.symptom_sign.v1]/items[at0001]/value
```
---
# まとめ

以上をSELECT, FROM, WHEREの順につなげます。

```
SELECT e/ehr_id/value, obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude, c/content[openEHR-EHR-OBSERVATION.story.v1]/data[at0001]/events[at0002]/data[at0003]/items[openEHR-EHR-CLUSTER.symptom_sign.v1]/items[at0001]/value FROM EHR e CONTAINS COMPOSITION c CONTAINS OBSERVATION obs [openEHR-EHR-OBSERVATION.temperature.v1]  WHERE obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude >= 38.0
```

Postmanから実行すると以下のような結果が返ってきます。

```
{
    "q": "SELECT e/ehr_id/value, obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude, c/content[openEHR-EHR-OBSERVATION.story.v1]/data[at0001]/events[at0002]/data[at0003]/items[openEHR-EHR-CLUSTER.symptom_sign.v1]/items[at0001]/value FROM EHR e CONTAINS COMPOSITION c CONTAINS OBSERVATION obs [openEHR-EHR-OBSERVATION.temperature.v1]  WHERE obs/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude >= 38.0",
    "columns": [
        {
            "path": "/ehr_id/value",
            "name": "#0"
        },
        {
            "path": "/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/magnitude",
            "name": "#1"
        },
        {
            "path": "/content[openEHR-EHR-OBSERVATION.story.v1]/data[at0001]/events[at0002]/data[at0003]/items[openEHR-EHR-CLUSTER.symptom_sign.v1]/items[at0001]/value",
            "name": "#2"
        }
    ],
    "rows": [
        [
            "04e27e6b-e9bf-4573-ae30-a3cd46a766c6",
            "38.0",
            {
                "value": "咳"
            }
        ],
        [
            "04e27e6b-e9bf-4573-ae30-a3cd46a766c6",
            "38.0",
            {
                "value": "発熱"
            }
        ],
        [
            "04e27e6b-e9bf-4573-ae30-a3cd46a766c6",
            "38.1",
            {
                "value": "倦怠感"
            }
        ],

```

---
# 参考資料

* openEHR Archetype Query Language, https://specifications.openehr.org/releases/QUERY/latest/AQL.html
* パスとロケーター: https://trac.openehr.jp/wiki/Archtectural%20Overview%20Paths
* openEHR REST Query API: https://specifications.openehr.org/releases/ITS-REST/Release-1.0.0/query.html#query-execute-query-post