iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0

前言

在上一篇文章中,我們認識了FHIR常見的資料型別,包括Identifier、HumanName、Coding、Quantity、Period及Reference。

其中,Reference是FHIR非常重要的資料型別,因為FHIR不會把病人的所有資料全部放進Patient Resource,而是將不同概念拆成獨立Resource,再利用Reference建立關係。

例如:

  • Patient記錄病人基本資料。
  • Encounter記錄一次就醫事件。
  • Observation記錄血壓、體溫或檢驗結果。
  • Practitioner記錄醫療人員資料。
  • Organization記錄醫療機構資料。

今天就來看看這些Resource如何透過Reference互相連結。

本文所有姓名、編號及醫療資料皆為虛構的教學資料。


為什麼Resource需要互相連結?

假設王小明到範例醫院看診,醫師替他量測體溫。

這個情境至少包含:

資料 對應Resource
王小明的基本資料 Patient
本次門診 Encounter
體溫測量結果 Observation
執行看診的醫師 Practitioner
提供服務的醫院 Organization

如果把病人的姓名、生日、醫師姓名及醫院資料全部重複放進每一筆Observation,可能產生以下問題:

  • 相同資料被重複儲存。
  • 病人改名後,需要修改許多筆Observation。
  • 每筆資料可能使用不同寫法。
  • 系統難以確認兩筆資料是否屬於同一位病人。
  • Resource會變得龐大且難以維護。

因此,FHIR會把資料拆成獨立Resource,再使用Reference建立連結。


用積木理解Reference

可以將每一筆Resource想像成獨立積木。

Patient/patient-001
王小明
        │
        ├── Encounter/encounter-001
        │   2026年9月3日門診
        │
        └── Observation/temperature-001
            體溫37.2°C

Patient、Encounter及Observation都是獨立資料。

Observation不需要重新放入病人的全部基本資料,只要透過Reference指出:

這筆體溫屬於Patient/patient-001

系統就能找到對應的Patient。


Reference的基本結構

一筆Reference可能包含以下欄位:

{
  "reference": "Patient/patient-001",
  "type": "Patient",
  "identifier": {
    "system": "https://hospital.example.org/mrn",
    "value": "MRN0001"
  },
  "display": "王小明"
}

Reference的常見欄位包括:

欄位 用途
reference 指向另一筆Resource的位置
type 說明目標Resource類型
identifier 使用業務識別碼指出對象
display 提供人類閱讀的文字

實際使用時不一定會同時放入所有欄位,要依照資料情境及Profile規定決定。


reference:指向Resource的位置

最常見的Reference寫法是:

{
  "reference": "Patient/patient-001"
}

可以拆成:

Resource類型 / Resource id

其中:

  • Patient是Resource類型。
  • patient-001是目標Patient的id。

如果FHIR Server的基礎網址是:

https://hospital.example.org/fhir

完整網址可能是:

https://hospital.example.org/fhir/Patient/patient-001

系統取得Reference後,就能依照位置讀取對應的Patient Resource。


相對Reference與絕對Reference

Reference可以使用相對位置或絕對網址。

相對Reference

{
  "reference": "Patient/patient-001"
}

它沒有包含完整FHIR Server網址,通常會相對於目前服務的基礎網址解析。

假設目前的FHIR Server是:

https://hospital.example.org/fhir

那麼:

Patient/patient-001

可能會被解析為:

https://hospital.example.org/fhir/Patient/patient-001

絕對Reference

{
  "reference": "https://hospital.example.org/fhir/Patient/patient-001"
}

絕對Reference直接包含完整網址。

可以簡單比較:

類型 範例
相對Reference Patient/patient-001
絕對Reference https://hospital.example.org/fhir/Patient/patient-001

相對Reference常用於同一個FHIR Server中的Resource;絕對Reference則能明確指出完整位置。

但實際上能否存取外部Server,仍取決於網路、權限、身分驗證及伺服器設定。


type:說明目標Resource類型

Reference中可以加入type

{
  "reference": "Patient/patient-001",
  "type": "Patient"
}

type用來明確表示目標Resource的類型。

在這個例子中,reference本身已經包含Patient,所以人類很容易看出目標類型。不過,在某些使用情境中,明確提供type仍能協助接收方確認Reference指向的Resource種類。


display:方便人類閱讀

{
  "reference": "Patient/patient-001",
  "display": "王小明"
}

display提供方便人類閱讀的文字。

當介面顯示這筆Reference時,可以直接呈現「王小明」,不必只顯示:

Patient/patient-001

但是,display不是建立Resource關係的主要依據。

因為可能有很多人都叫王小明,所以系統不能只使用:

{
  "display": "王小明"
}

就認定這筆資料屬於哪位病人。

在上面的範例中,真正指向目標Resource的是:

"reference": "Patient/patient-001"

display主要是輔助閱讀,也可能與目標Resource目前的資料不同步,因此不應把它當成唯一或最可靠的資料來源。


使用identifier指出對象

有時候,系統知道病人的病歷號,卻不知道對方FHIR Server中的Patient id。

這時Reference可以使用Identifier:

{
  "identifier": {
    "system": "https://hospital.example.org/mrn",
    "value": "MRN0001"
  },
  "display": "王小明"
}

這代表:

目標是病歷號系統https://hospital.example.org/mrn中,編號為MRN0001的對象。

這種方式稱為Logical Reference,也就是透過業務識別資料指出對象,而不是直接提供Resource網址。

Literal Reference

{
  "reference": "Patient/patient-001"
}

直接指向某一筆Resource的位置。

Logical Reference

{
  "identifier": {
    "system": "https://hospital.example.org/mrn",
    "value": "MRN0001"
  }
}

透過Identifier描述目標對象。

兩種方式的概念可以整理成:

類型 依據 範例
Literal Reference Resource位置或網址 Patient/patient-001
Logical Reference 業務識別碼 病歷號MRN0001

Logical Reference並不保證接收系統一定能自動找到目標Resource。系統仍要具備查詢及比對該Identifier的能力。


Patient Resource

先建立一筆簡化的Patient:

{
  "resourceType": "Patient",
  "id": "patient-001",
  "identifier": [
    {
      "system": "https://hospital.example.org/mrn",
      "value": "MRN0001"
    }
  ],
  "name": [
    {
      "text": "王小明",
      "family": "王",
      "given": [
        "小明"
      ]
    }
  ],
  "gender": "male",
  "birthDate": "2000-01-01"
}

這筆Resource的邏輯位置是:

Patient/patient-001

後續的Encounter與Observation都可以使用這個位置連回Patient。


Encounter如何連結Patient?

以下是一筆簡化的門診Encounter:

{
  "resourceType": "Encounter",
  "id": "encounter-001",
  "status": "finished",
  "class": {
    "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
    "code": "AMB",
    "display": "ambulatory"
  },
  "subject": {
    "reference": "Patient/patient-001",
    "display": "王小明"
  },
  "period": {
    "start": "2026-09-03T09:00:00+08:00",
    "end": "2026-09-03T09:20:00+08:00"
  }
}

其中:

"subject": {
  "reference": "Patient/patient-001",
  "display": "王小明"
}

表示這次就醫事件的對象是王小明。

Encounter本身不必再放入王小明的出生日期、電話及地址。如果系統需要這些資料,可以依照Reference讀取Patient。


Observation如何同時連結Patient和Encounter?

以下是一筆簡化的體溫Observation:

{
  "resourceType": "Observation",
  "id": "temperature-001",
  "status": "final",
  "code": {
    "text": "體溫"
  },
  "subject": {
    "reference": "Patient/patient-001",
    "display": "王小明"
  },
  "encounter": {
    "reference": "Encounter/encounter-001",
    "display": "2026年9月3日門診"
  },
  "effectiveDateTime": "2026-09-03T09:05:00+08:00",
  "valueQuantity": {
    "value": 37.2,
    "unit": "°C",
    "system": "http://unitsofmeasure.org",
    "code": "Cel"
  }
}

這筆Observation包含兩個Reference。

subject

"subject": {
  "reference": "Patient/patient-001"
}

表示這項體溫結果屬於哪一位病人。

encounter

"encounter": {
  "reference": "Encounter/encounter-001"
}

表示這項體溫是在王小明哪一次就醫過程中產生。

因此,系統可以知道:

王小明在2026年9月3日這次門診中,量測到體溫37.2°C。


Encounter還能連結哪些Resource?

Encounter除了可以連結Patient,也可能連結:

  • Practitioner
  • Organization
  • Location
  • Appointment
  • EpisodeOfCare
  • HealthcareService

例如,記錄參與看診的醫師:

"participant": [
  {
    "individual": {
      "reference": "Practitioner/doctor-001",
      "display": "陳醫師"
    }
  }
]

記錄提供服務的醫院:

"serviceProvider": {
  "reference": "Organization/hospital-001",
  "display": "範例醫院"
}

這樣就能將病人、醫療人員、醫院及本次就醫事件串在一起。


完整關係整理

目前建立的Resource關係可以整理如下:

Organization/hospital-001
範例醫院
        │
        └── Encounter/encounter-001
            2026年9月3日門診
                 │
                 ├── Patient/patient-001
                 │   王小明
                 │
                 ├── Practitioner/doctor-001
                 │   陳醫師
                 │
                 └── Observation/temperature-001
                     體溫37.2°C

從不同方向理解:

  • Encounter的subject指向Patient。
  • Encounter的participant.individual指向Practitioner。
  • Encounter的serviceProvider指向Organization。
  • Observation的subject指向Patient。
  • Observation的encounter指向Encounter。

Reference的方向很重要

如果Observation中寫著:

"subject": {
  "reference": "Patient/patient-001"
}

表示Observation指向Patient。

但是,Patient Resource本身不一定會列出所有指向它的Observation。

也就是說,讀取:

GET /Patient/patient-001

通常只會取得Patient Resource,不會自動把病人的所有Observation一起放進回應。

如果要找這位病人的Observation,可能需要另外搜尋:

GET /Observation?patient=patient-001

實際支援的搜尋參數要以FHIR Server的CapabilityStatement及Resource規範為準。

Reference建立了資料關係,但不代表讀取其中一筆Resource時,系統一定會自動回傳所有相關Resource。


Reference和display內容不同怎麼辦?

假設Reference寫成:

{
  "reference": "Patient/patient-001",
  "display": "王小華"
}

但實際讀取Patient/patient-001後,Patient姓名是王小明。

這時應該以實際目標Resource中的資料及系統規則為準,不能只依靠display判斷。

display可能是:

  • 建立Reference當下的顯示文字
  • 方便使用者閱讀的摘要
  • 尚未同步更新的內容
  • 由來源系統自行產生的文字

所以display不應取代正式Resource內容。


Reference指向不存在的Resource會怎樣?

假設Observation包含:

"subject": {
  "reference": "Patient/patient-999"
}

但是FHIR Server中沒有Patient/patient-999,這個Reference就可能無法解析。

可能原因包括:

  • Resource尚未建立。
  • id輸入錯誤。
  • Patient已經被刪除。
  • Resource存在於另一台Server。
  • 使用者沒有讀取權限。
  • 資料匯入順序不正確。

一份JSON可能在語法上完全正確,但Resource之間的關係仍然可能失效。因此,FHIR驗證不只要檢查欄位,也可能需要確認Reference的目標是否存在及是否符合預期類型。


Reference可以指向錯誤的Resource類型嗎?

假設Observation的subject預期指向Patient,卻寫成:

"subject": {
  "reference": "MedicationRequest/medication-001"
}

即使這筆MedicationRequest真的存在,也不代表這個Reference符合Observation對subject的規定。

FHIR每一個Reference欄位都會限制可以指向哪些Resource類型。

查看FHIR官方Resource頁面時,可以看到Reference允許的目標類型。例如,欄位的資料型別可能顯示:

Reference(Patient | Group | Device | Location)

表示它只能指向列出的Resource類型。


Contained Resource簡介

FHIR也允許某些Resource被放在另一筆Resource的contained中。

這種Resource不會擁有獨立的外部位置,而是在目前Resource內使用#進行Reference。

簡化範例如下:

{
  "resourceType": "Observation",
  "id": "observation-001",
  "contained": [
    {
      "resourceType": "Practitioner",
      "id": "doctor-001",
      "name": [
        {
          "text": "陳醫師"
        }
      ]
    }
  ],
  "performer": [
    {
      "reference": "#doctor-001",
      "display": "陳醫師"
    }
  ]
}

其中:

"reference": "#doctor-001"

表示Reference指向目前Resource內部包含的Practitioner。

Contained Resource有特定使用規則,通常是在目標資料無法或不適合獨立存在時使用。初學階段先知道#id代表Resource內部的Reference即可。


閱讀Reference的步驟

看到Reference時,可以依照以下順序閱讀:

第一步:Reference出現在哪個欄位?

例如:

  • subject
  • encounter
  • performer
  • managingOrganization
  • serviceProvider

欄位名稱會告訴我們這段關係的用途。

第二步:目標是哪一種Resource?

查看:

"reference": "Patient/patient-001"

目標類型是Patient。

第三步:目標的id是什麼?

在上面的例子中,id是:

patient-001

第四步:是否提供display?

"display": "王小明"

它可以協助人類閱讀,但不是唯一識別依據。

第五步:是否改用identifier?

如果沒有Resource位置,就查看是否使用identifier.systemidentifier.value指出目標。


今日練習

請觀察以下Resource:

{
  "resourceType": "Condition",
  "id": "condition-001",
  "subject": {
    "reference": "Patient/patient-001",
    "display": "王小明"
  },
  "encounter": {
    "reference": "Encounter/encounter-001"
  },
  "recorder": {
    "reference": "Practitioner/doctor-001",
    "display": "陳醫師"
  }
}

可以找出三段關係:

  1. subject指向Patient,表示診斷屬於哪位病人。
  2. encounter指向Encounter,表示診斷與哪次就醫有關。
  3. recorder指向Practitioner,表示由哪位人員記錄。

一筆Condition不需要重複存放病人及醫師的全部資料,透過Reference就能建立彼此關係。


今日小結

今天認識了FHIR Resource之間的連結方式。

Reference常見欄位包括:

  • reference:目標Resource的位置
  • type:目標Resource類型
  • identifier:目標對象的業務識別碼
  • display:方便人類閱讀的文字

Reference可以使用相對位置、絕對網址或Identifier指出目標,也能使用#id指向Contained Resource。

我認為今天最重要的觀念是:

FHIR將醫療資料拆成獨立Resource,再透過Reference建立關係。

Patient不需要保存所有就醫、檢驗及用藥資料;Encounter和Observation也不需要重複放入病人的完整基本資料。透過Reference,這些獨立Resource仍然可以組成完整的醫療情境。

下一篇將介紹另一個讓不同系統理解醫療資料的重要基礎——醫療代碼。

明日預告

Day 12|醫療代碼為什麼這麼重要?

參考資料

  1. HL7 FHIR R4:References
    https://hl7.org/fhir/R4/references.html

  2. HL7 FHIR R4:Resource References
    https://hl7.org/fhir/R4/resource.html#references

  3. HL7 FHIR R4:Patient
    https://hl7.org/fhir/R4/patient.html

  4. HL7 FHIR R4:Encounter
    https://hl7.org/fhir/R4/encounter.html

  5. HL7 FHIR R4:Observation
    https://hl7.org/fhir/R4/observation.html


上一篇
Day 10|FHIR常見資料型別一次看懂
下一篇
Day 12|醫療代碼為什麼這麼重要?
系列文
《醫資生的 FHIR 30日入門:用 Postman 讀懂醫療資料交換》30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言