大多数工程师从没见过真实的 HL7 消息。

如果你在 fintech 工作过,你可能解析过 ISO 8583。如果你在物流工作过,你处理过 EDI。如果你在医疗数据工作过——具体地说,如果你构建过两个医院系统之间的实时集成——你见过 HL7 v2,而且你对它有了之前没有的看法。

我写了 King Hussein 癌症中心(KHCC)和 HAKEEM(约旦国家 EHR)之间的 HL7 集成,当时在 Electronic Health Solutions 工作,2010 到 2013 年。这是它实际上的样子。

HL7 v2 消息长什么样

从 wire format 开始,因为这是第一个让工程师做鬼脸的东西。

MSH|^~\&|KHCC|KHCC|HAKEEM|MOH|20120315120000||ADT^A01|MSG00001|P|2.3
EVN|A01|20120315120000
PID|1||12345^^^KHCC^MR||AL-MANSOUR^AHMAD^MOHAMMED||19750304|M|||AMMAN^JO||||AR|M||12345
PV1|1|I|ONCOLOGY^101^1^KHCC||||SMITH^JOHN^A^^^DR||||||||ONCOLOGY|||V|||||||||||||||||||||||20120315

这是一个 ADT^A01——入院/出院/转院消息,事件 A01 表示患者入院。每个段用竖线分隔。段内的字段用竖线分隔。子字段用 ^ 分隔。子子字段用 &。重复字段用 ~

MSH 段是消息头:发送应用、发送机构、接收应用、接收机构、时间戳、消息类型、消息 ID、处理 ID、版本。PID 段是患者标识符:患者 ID 列表(可以有很多,来自很多系统)、姓名、出生日期、性别、地址、语言、婚姻状况、宗教、账户号。

HL7 v2.3——我们当时使用的版本——在 1997 年定稿。竖线分隔格式可以追溯到带宽昂贵、XML 还没征服企业世界的时代。它不漂亮。它直接映射到医院系统实际存储和交换患者数据的方式,这就是为什么几十年后它仍然是医疗领域的主流 wire format,尽管 FHIR、CDA 和其他每个本该取代它的标准已经存在。

为什么 KHCC 是一个特别的集成挑战

King Hussein 癌症中心不是综合医院。它是一个专科肿瘤机构。患者通过其他医院转诊到 KHCC——其中很多在约旦国家系统里已经在 HAKEEM 上了。

这意味着患者的记录不是在 KHCC 开始的。它在转诊机构开始——比如 Prince Hamza 医院——患者在那里最初被诊断出需要肿瘤专科的疾病。那份患者记录包括他们的人口学信息、初始诊断、用药史、检验结果。这一切都在 HAKEEM 里。

当那个患者到达 KHCC 接受癌症治疗时,KHCC 有自己的 EHR。自己的患者 ID 空间。自己的临床概念数据模型,比如化疗方案、放疗计划和肿瘤专属检验组合。挑战不只是”把 KHCC 的数据导入 HAKEEM”。挑战是在两个给同一个人分配了不同 ID 的系统之间做患者身份解析,然后是双向记录同步,让两个系统保持最新状态,同时不产生重复记录或丢失临床上下文。

HL7 v2 是这个问题的传输层。它不是这个问题的解决方案。解决方案是患者匹配算法、主患者索引和一个理解哪个系统里的哪些事件应该触发发送到另一个系统的消息的消息路由层。

真正难的部分

以下是”只是解析 HL7”没有说的。

患者身份不是一个已解决的问题。 KHCC 分配了他们自己的病历号(MRN)。HAKEEM 维护着自己的国家患者标识符体系。PID 段有一个患者 ID 列表的字段——PID-3——专门是因为患者在多个系统有多个标识符。但知道患者在 KHCC 是 12345 而在 HAKEEM 是 98765,需要一张映射表。构建那张表需要一个自动概率匹配算法(按姓名+出生日期+性别+地址匹配,打分可信度),或者手动对账流程,或者——在实践中——两者兼有,针对不同可信度阈值有不同规则。

事件排序在临床上很重要。 HL7 ADT 消息携带事件类型——A01 是入院,A02 是转科,A03 是出院,A08 是患者信息更新。这些事件必须按顺序到达,按顺序处理,否则你的临床图景是错的。一个被入院(A01)、转科(A02)、然后出院(A03)的患者,和那些消息乱序到达并被处理为入院、出院、然后转到他们已经离开的科室的患者,看起来是截然不同的。

在高流量的医院集成中,消息不总是按顺序到达。TCP 给你可靠投递;在消息被不同系统异步产生时,它不给你应用级排序保证。你需要序列号,需要消息确认(ACK/NAK),以及一个带重试逻辑的队列,处理 NAK 而不丢失消息或向目标系统发送大量重复消息。

发送系统的实现才是真正的规范。 HL7 v2.3 是一个标准。但标准有可选字段、可选段,以及相当大的实现变化空间。KHCC 的 EHR 实际上在 PID-3 里发送什么才是重要的——不是 HL7 规范说应该在那里的。我花了大量时间和 KHCC 技术团队一起分析他们实际的出站消息来理解我们会收到什么,因为实现文档是不完整的。这很正常。我听说的每个 HL7 集成都有这个故事的某个版本。

消息路由层是什么样子

HAKEEM-KHCC 集成使用了 VistA 里的 HL7 Messaging 包——那个包里的 MUMPS 例程在 HAKEEM 侧处理入站消息解析和路由。我写了处理特定事件类型的例程——主要是用于患者移动的 ADT 事件,以及用于检验医嘱和结果的 ORM/ORU 对。

转诊流程:

  1. 转诊医院(在 HAKEEM 上)把患者送往 KHCC。
  2. KHCC 在他们的系统里注册患者,分配他们的 MRN。
  3. KHCC 向 HAKEEM 发送 ADT^A01 确认入院。
  4. HAKEEM HL7 路由层接收 A01,通过 MPI 映射解析患者身份,并用 KHCC 的就诊信息更新 HAKEEM 里的患者记录。
  5. 来自 KHCC 肿瘤检验组合的检验结果通过 ORU^R01 消息回流,落到患者的 HAKEEM 记录里,对仍然持有患者首要护理关系的转诊医师可见。

最后这点在临床上很重要。KHCC 的肿瘤科医生在治疗癌症。转诊医院的全科医生还在管理患者的高血压、糖尿病和其他一切。他们需要看到肿瘤科的结果。HL7 集成就是让这成为可能而不需要患者在医疗机构之间带着纸质记录的东西。

十二年后我对 HL7 的看法

HL7 v2 不是漂亮的软件。但它是那种赢得你尊重的丑陋:丑陋是因为问题域是丑陋的,不是因为设计者没有努力。

医疗数据是混乱的,因为医疗是混乱的。患者有多个标识符是因为他们和多个系统打交道。事件有排序要求是因为临床时间线对诊断和治疗很重要。让规范看起来松散的字段可选性,是因为不同的临床专科有不同的数据需求,而标准必须服务于所有人。

FHIR 在大多数方面真正更好——RESTful、JSON 或 XML、面向资源、现代工具链。它也年轻了十二年。2012 年,FHIR 是一份草案规范。HL7 v2 是医院系统讲的语言。你和存在的东西集成。

构建医疗集成的工程师在做大多数行业看不见、不去想的工作。把你的检验结果从检验系统传到你的病历再传到你医生屏幕上的 HL7 消息是管道。没有人注意到管道,直到它坏掉。

我注意到了管道。我构建了其中的一部分。管道还在跑。