4. FHIR 资源模型与 RESTful API

FHIR 之所以能成为跨机构医疗数据交换的主流标准,核心在于它把医疗数据抽象为“资源(Resource)”,并用一套统一的 RESTful 接口来读写这些资源。理解 FHIR,本质上要同时理解两件事:资源模型描述“数据长什么样”,RESTful API 描述“数据怎么被访问和交换”。两者缺一不可。

一、资源模型:FHIR 的数据基本单元

在 FHIR 中,一切可独立交换的数据都是资源。每个资源都有统一的骨架:resourceType 标识资源类型,id 是资源在某个服务器内的唯一标识,meta 记录版本与最后更新时间,text 可存放供人阅读的叙述性内容。除此之外,资源通过 Reference 相互引用,形成一张可导航的数据网络,而不是一棵封闭的树。

跨机构交换中最常用的核心资源包括:

  • Patient(患者):描述接受医疗服务的个体,包含姓名、性别、出生日期、标识符(如身份证号、医保号、院内病案号)等。它是几乎所有临床资源的“锚点”。
  • Encounter(就诊):描述一次具体的医疗服务接触,如门诊、住院、急诊。它把某段时间内发生的观察、诊断、用药等事件聚合在一起,是临床时间线的组织者。
  • Observation(观察):描述对患者某项指标的测量或判断,如血压、血糖、体温、检验结果。它通常包含编码(code)、值(valueQuantity 或 valueCodeableConcept)、状态(status)和发生时间(effectiveDateTime)。
  • Condition(病情/诊断)、MedicationRequest(用药请求)、DiagnosticReport(诊断报告) 等,则分别承载诊断、医嘱和报告类信息。

这些资源之间通过引用连接:Observation 通过 subject 指向 Patient,通过 encounter 指向 Encounter;Encounter 通过 subject 指向 Patient。这种引用关系决定了数据交换时的“抓取路径”——拿到一个患者,就能顺着引用拉取其全部就诊与观察记录。

二、RESTful API:资源的访问方式

FHIR 定义了一套基于 HTTP 的交互风格,核心操作与 HTTP 方法一一对应:

操作HTTP 方法典型 URL说明
读取GET/Patient/123按 id 读取单个资源
搜索GET/Observation?patient=123&code=8867-4按条件查询资源集合
创建POST/Patient提交新资源,服务器分配 id
更新PUT/Patient/123整体替换指定资源
删除DELETE/Patient/123删除或标记资源

搜索是跨机构交换中使用最频繁的交互。FHIR 为每种资源定义了标准搜索参数,例如 Patient 支持 identifier、name、birthdate;Observation 支持 patient、code、date。搜索返回的是一个 Bundle 资源,类型为 searchset,其中 entry 数组承载匹配结果,total 表示总数,link 中的 next 用于分页。

三、交互设计:从单次调用到完整交换

实际工程中,一次跨机构数据交换往往不是单次请求,而是一组有依赖关系的调用。以“从协作医院拉取某患者近一个月的血糖观察记录”为例,典型交互链如下:

  1. 用患者标识符搜索:GET /Patient?identifier=医保号,从返回 Bundle 中取出 Patient.id。
  2. 用 Patient.id 搜索观察:GET /Observation?patient=Patient.id&code=2339-0&date=ge2024-05-01。
  3. 若需要就诊上下文,再按 encounter 引用回查 Encounter 资源。

这条链的关键在于:每一步的输入来自上一步的输出,且必须处理“未找到”“多条匹配”“分页未取完”等边界情况。设计时通常要求:搜索命中多条时按 meta.lastUpdated 或业务规则选定主记录;分页时循环跟随 next 链接直到取完。

跨机构场景下,建议优先使用 identifier 搜索而非姓名,因为姓名在不同机构间重名率高,而医保号、身份证号等标识符具有更强的唯一性。

四、资源引用与数据完整性

FHIR 资源之间的引用有两种常见形态:相对引用(如 Patient/123)和绝对引用(如 https://hospital-a.example/fhir/Patient/123)。跨机构交换时,绝对引用能明确指向数据来源,但会暴露内部地址;相对引用更简洁,但需要交换双方约定基础 URL。工程上常采用“相对引用 + 交换时重写”的策略,在网关层统一替换为对端可解析的地址。

此外,资源中的 status 字段不可忽视。Observation 的 status 可为 registered、preliminary、final、amended、cancelled,只有 final 或 amended 的结果才应被视为可用于临床决策。交换时若忽略状态过滤,可能把未审核的中间结果当作最终结论,造成误判。

FHIR 核心资源引用关系与 RESTful 交互链 Patient identifier / name birthDate / gender 资源锚点 Encounter status / class period / subject 就诊时间线组织者 Observation code / valueQuantity status / effectiveDateTime 测量与判断结果 subject encounter Observation.subject → Patient(直接引用) RESTful 交互链:按标识符拉取患者血糖观察 ① 搜索患者 GET /Patient?identifier=… → Bundle(searchset) ② 搜索观察 GET /Observation?patient=… &code=2339-0&date=ge… ③ 回查就诊 GET /Encounter/{id} 补全就诊上下文 边界处理 未找到 → 终止并记录;多条匹配 → 按 lastUpdated 选定;分页 → 循环跟随 link.next 直到取完 状态过滤:仅 status=final / amended 的结果可用于临床决策

五、工程实现要点

在真实网关或集成引擎中实现上述交互时,需要关注以下几点。第一,认证与授权:FHIR 服务器通常要求 OAuth 2.0 的 Bearer Token,跨机构场景还需 SM 2 或 TLS 双向认证保障传输安全。第二,版本与并发:更新资源时可通过 If-Match 携带 ETag,避免覆盖他人修改。第三,Bundle 批处理:当需要一次提交多个资源时,可使用 Bundle.type=batch 或 transaction,服务器按条目逐一处理并返回结果,减少往返次数。第四,错误处理:FHIR 用 OperationOutcome 资源描述错误,包含 issue.severity、issue.code 和 diagnostics,调用方应解析该资源而非仅看 HTTP 状态码。

GET /Observation?patient=123&code=2339-0&date=ge2024-05-01
Accept: application/fhir+json
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/fhir+json

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 2,
  "entry": [
    {
      "resource": {
        "resourceType": "Observation",
        "id": "obs-001",
        "status": "final",
        "code": { "coding": [{ "system": "http://loinc.org", "code": "2339-0" }] },
        "subject": { "reference": "Patient/123" },
        "effectiveDateTime": "2024-05-10T08:30:00+08:00",
        "valueQuantity": { "value": 6.1, "unit": "mmol/L" }
      }
    }
  ]
}

这段示例展示了搜索返回的 Bundle 结构:total 为 2 表示共两条匹配,entry 中每条包含一个 Observation 资源,其 status 为 final,code 使用 LOINC 编码,valueQuantity 给出数值与单位。调用方应遍历 entry,提取所需字段,并检查 link 中是否存在 next 以决定是否继续分页。

跨机构交换时,编码系统必须对齐。若 A 院用 LOINC 编码血糖,B 院用本地编码,直接按 code 搜索会漏检。工程上需在网关层做编码映射,或使用 CodeableConcept 的多编码能力同时携带本地码与标准码。

总结来看,FHIR 资源模型提供了标准化的数据结构和引用关系,RESTful API 提供了统一的访问方式,而交互设计则决定了这些能力能否在跨机构场景中稳定落地。掌握 Patient、Encounter、Observation 三类核心资源的字段含义、引用方向和搜索参数,是构建任何 FHIR 交换链路的基础。