# HAPI FHIR ValueSet Expand 為 0 的問題
## 前言
某天同事收到了別人發過來的 issue,問題大致為 HAPI FHIR 已上傳 Snomed CT 的 Code 以及 IG Package,但是上傳範例上去時,ValueSet 會報找不到 Code 的錯誤
在經過一小番研究後,終於大致譜出 HAPI FHIR 的 ValueSet 尋找 Code 的方式,筆者認為這機制挺有意思的,必須記錄一下錯誤重現 (Error Reproduction) 以及目前找到的解決方法
## 錯誤重現
- 首先,準備一台完全乾淨的 HAPI FHIR Server (這裡使用的是 v7.2.0 版本,記憶體建議 16 gb 以上)
- 請記得在 `application.yaml` 先設定 `hibernate.search.enabled: true`
### 上傳 Terminology Code
以下的 Code 都是使用 HAPI FHIR [官方的 CLI 工具](https://hapifhir.io/hapi-fhir/docs/tools/hapi_fhir_cli.html)上傳
#### 上傳過程
- 上傳任何一個 Terminology Code 時,都會進行將 Code 儲存的動作,以下是 Code 儲存過程的 Log

- 當出現 `All deferred concepts and relationships have now been synchronized to the database` 就代表 Code 儲存完成囉!

:::danger
⚠️ 請等到 Code 完全處理完成,再進行下一個 Code 的上傳
:::
#### 上傳 Snomed CT
```!
./hapi-fhir-cli upload-terminology -d ${snomed-zip} -v r4 -t http://localhost:8080/fhir -u http://snomed.info/sct -s 10GB
```
- 若你遇到 Java heap space 的問題你可以試試看
```!
java -Xmx6g -jar ./hapi-fhir-cli.jar upload-terminology -d ${snomed-zip} -v r4 -t http://localhost:8080/fhir -u http://snomed.info/sct -s 10GB
```
#### 上傳 LOINC
- 這裡使用的是 Loinc V2.73版本
```!
./hapi-fhir-cli upload-terminology -d ${loinc-zip} -d ${loinc-properties} -v r4 -t http://localhost:8080/fhir -u http://loinc.org -s 10GB
```
- 其中 loinc-properties 的檔案內容如下
```!
loinc.hierarchy.file=AccessoryFiles/ComponentHierarchyBySystem/ComponentHierarchyBySystem.csv
loinc.codesystem.version=2.73
```
### 展開 ValueSet
- 以下展開的是 snomed 的 valueset
- 開啟 postman
- 網址輸入:`http://localhost:8080/fhir/ValueSet/$expand`
- Method 選擇:`POST`
- body 使用 json 並使用以下 resource
```json!=
{
"resourceType": "Parameters",
"parameter": [
{
"name": "valueSet",
"resource": {
"resourceType": "ValueSet",
"compose": {
"include": [
{
"filter": [
{
"property": "concept",
"op": "is-a",
"value": "399097000"
}
]
}
]
}
}
}
]
}
```
> 這裡展開的範例是醫查的 [SNOMED CT Anesthesia值集](https://hitstdio.ntunhs.edu.tw/imri/ValueSet-anesthesia-sct.html#root)
- 展開結果,可以看到展開後的結果為 0
```json!=
{
"resourceType": "ValueSet",
"meta": {
"extension": [
{
"url": "http://hapifhir.io/fhir/StructureDefinition/valueset-expansion-message",
"valueString": "ValueSet with URL \"Unidentified ValueSet\" was expanded using an in-memory expansion"
}
]
},
"status": "active",
"compose": {
"include": [
{
"system": "http://snomed.info/sct",
"filter": [
{
"property": "concept",
"op": "is-a",
"value": "399097000"
}
]
}
]
},
"expansion": {
"identifier": "f906cf29-2b33-435e-9e61-9f24923ee7c3",
"timestamp": "2024-07-07T14:38:24+00:00",
"offset": 0,
"parameter": [
{
"name": "offset",
"valueInteger": 0
},
{
"name": "count",
"valueInteger": 1000
}
]
}
}
```
## 解決過程
### ValueSet 展開需打開 hibernate.search.enabled 功能
- 由於筆者一開始是使用同事架好的 HAPI FHIR,怎麼試都找不到解決方法,回到家後,決定自己架一台測試,結果一用 ValueSet 的 $expand 功能卻跑出了以下錯誤

- 要解決不能使用 $expand 功能的問題,請到 application.yaml將`hibernate.search.enabled` 選項開啟
```
### These settings will enable fulltext search with lucene or elastic
hibernate.search.enabled: true
```
- 當你仔細看到這個設定時,會看到上面的註解`These settings will enable fulltext search with lucene or elastic`,看到這邊,筆者就發現不對勁,原來 ValueSet 的 Code 查詢方法是從 lucene 或 elasticsearch 來的 (預設是 lucene)
### ValueSet $expand 尋找 Code 的過程
以下是筆者大致猜測 ValueSet $expand 尋找 Code 的過程,若是想知道真實過程,還請大神們看 HAPI FHIR 的 Source Code 推導並分享分享
1. 進行 ValueSet $expand 動作
2. HAPI FHIR 會去找 Lucene index 的 code (展開為 0 大概是因為 Lucene 的 index 出錯)
3. 將 Lucene index 的 code 展開
4. 將 code 儲存至 trm_valueset_concept 的 table 內,以便後續使用

:::info
ℹ️ Lucene 是使用檔案系統進行 index 的,若你想找到 Lucene index 的檔案,可以將 /app/target/lucenefiles 給 volumn 出來
:::
### 解決方案 Reindex Terminology
在 HAPI FHIR 的官方文件當中有提到 [Reindex Terminology](https://hapifhir.io/hapi-fhir/docs/tools/hapi_fhir_cli.html#reindex-terminology) 的指令: The reindex-terminology command may be used to recreate freetext indexes for terminology resources.
上面筆者推測是 Lucene 的 index 出錯了,所以重跑了這段指令看看,結果!!!expand 的結果就正常了
#### Reindex Terminology
- 使用 hapi-fhir-cli 指令執行 reindex terminology
```!
./hapi-fhir-cli reindex-terminology -v r4 -t "http://localhost:8080/fhir"
```
- 執行後,HAPI FHIR 會出現準備重新 Index 多少資料的 Log

- 過程中都會出現進度條的 Log,當完成時,會出現 Re-creating terminology freetext indexes took {time}

#### 重新展開 ValueSet
重新執行[展開 ValueSet]後的結果如下(https://app.gitbook.com/o/ksml8wtewJVGJzK6ckE5/s/OLTFnZLfnxYlZrUiz9zr/#zhan-kai-valueset)

## 參考資料
1. https://hapifhir.io/hapi-fhir/docs/tools/hapi_fhir_cli.html
2. https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html
## Support Me
文件創作花費了很多心血製作,如果你覺得很有幫助
不妨贊助我一下喝杯咖啡唄,[Support Me](https://portaly.cc/Li070/support)