文章
· 十月 8 阅读大约需 5 分钟

FHIR Object Model 简介

挑战

在使用FHIR进行开发的过程中,我们会面对海量的FHIR规范中定义的数据结构,具体来说在FHIR规范中定义了超过150个资源、700多个资源内元素。每个定义里都包括了对自身结构的描述以及数据约束、数据绑定值集等。对于一个开发人员要记住这些内容非常困难。

同时FHIR数据,特别是Json格式的FHIR数据是典型的“有向图”结构,它的资源中嵌套元素定义、集合以及复杂的资源间“关系”,在这些复杂结构的数据间导航并操作,非常困难。

解决方案

在InterSystems IRIS for Health 2024.1之前,我们会将FHIR数据以Json文档的方式载入 %DynamicAbstractObject,例如下面的代码

   set dynObject1 = ##class(%DynamicObject).%New()
   set dynObject1.SomeNumber = 42
   set dynObject1.SomeString = "a string"
   set dynObject1.SomeArray = ##class(%DynamicArray).%New()
   set dynObject1.SomeArray."0" = "an array element"
   set dynObject1.SomeArray."1" = 123
   set dynObject2 = {"SomeNumber":42,"SomeString":"a string"}
   set dynObject2.SomeArray = ["an array element",123]
   
   write "object 1: "_dynObject1.%ToJSON(),!,"object 2: "_dynObject2.%ToJSON()

可以看到这样的处理有下面不方便的地方:

  • 只能使用自己的方式解析、导航FHIR结构
  • 不能从IDE中获取提示信息
  • 没有数据类型安全
  • 没有上下文敏感的文档
  • 没有调试debug的支持

在InterSystems IRIS for Health 2024.1版本之后,引入了FHIR 对象模型。

FHIR 对象模型概览

在 HS.FHIRModel.R4 包下,每一个FHIR R4资源都对应一个ObjectScript类。比如 HS.FHIRModel.R4.AllergyIntolerance类对应于 AllergyIntolerance 资源。这些类通过为资源和组成元素提供一个共享的、可预测的数据结构和方法框架,简化了开发过程。

这样的结构,在VS Code环境下,会给出很好的提示

下面具体举例如何使用FHIR 对象模型:

1. 获取数据

按索引获取有序序列中的值

 Set patientName = patient.name.get(0)

获取嵌套定义中的值

 Set patientIdValue = patient.identifier.get(0).get(“value”)
 Set patientCity = patient.address.get(0).city

在获取数据前判断键key是否存在

 If patient.name.get(0).contains("family") {
     Set familyName = patient.name.get(0).get(“family”) 
 }

2. 更新数据

添加新的键值对

 Do patient.name.get(0).put("use","official")

更新存在的值

 Do observation.put("status","final")

3. 添加对象的引用

 Set claim = ##class(HS.FHIRModel.R4.Claim).%New()
 Do claim.IncludeType()
 Do claim.type.IncludeCoding()

4. 导航对象

 Set contactItr = patient.contact.get(0).telecom.iterator()
 While contactItr.hasNext() {
    Set contact = contactItr.next().value
    if contact.system = "phone" {
        Write !, contact.value
    }
 }

5 读取JSON格式 FHIR 数据

 Set rType = dao.resourceType
 Set cls = $CLASSMETHOD("I4H.FhirR4."_rType,"fromDao",dao)

6. 将FHIR 数据输出为 JSON 格式

 Set newDao = cls.toDao()

转为字符串

 Set payload = cls.toString()

7. 创建新的 FHIR 元素

 Do claim.IncludeType()
 Do claim.type.IncludeCoding()
 Set coding = ..MakeCoding("http://terminology.hl7.org/CodeSystem/claim-type","institutional")
 Do claim.type.coding.add(coding)

8. “图” 结构查询引擎

 Set key = "system"
 Set value = "email"
 Set query = "$[*]?(@."_key_"=='"_value_"')"
 Set email = doctor.telecom.apply(query)

更多资料

FHIR Object Model 在线文档:https://docs.intersystems.com/irisforhealth20242/csp/docbook/DocBook.UI.Page.cls?KEY=HXFHIR_data#HXFHIR_data_classes

 

下面是一个完整的创建患者资源的例子

ClassMethod MakeCoding(system As %String, code As %String, display As %String = "") As HS.FHIRModel.R4.Coding
{
    Set rec = ##class(HS.FHIRModel.R4.Coding).%New()
	Set rec.system = system
	Set rec.code = code
	If (display'="") Set rec.display = display
	Return rec
}

// Create a Patient using FHIR Object Model classes from R4 and then post
// this patient on the FHIR server
ClassMethod CreatePatient(ident As %String) As %Status
{
   #dim patient As HS.FHIRModel.R4.Patient
   Set patient = ##class(HS.FHIRModel.R4.Patient).%New()
   Do patient.IncludeName()
   Set name = patient.name.MakeEntry()
   Set firstName = "John"
   Do name.IncludeGiven()
   Do name.given.add(firstName)
   Set name.family = "Doe"
   Do patient.name.add(name)

    If patient.name.get(0).contains("family") {
    Set fName = patient.name.get(0).get("family") 
    }

    Do patient.name.get(0).put("use","official")

   Set patient.gender = "male"
   Set patient.birthDate = "1985-05-15"
   Do patient.IncludeAddress()
   Set addr = patient.address.MakeEntry()
   Do addr.IncludeLine()
   Set line1 = "123 Main Street"
   Do addr.line.add(line1)
   Set addr.city = "Boston"
   Set addr.state = "MA"
   Set addr.postalCode = "02111"
   Do patient.address.add(addr)

   Set address = ##class(HS.FHIRModel.R4.Address).%New()
   Do patient.put("address", address)

   Do patient.IncludeContact()
   Set contact = patient.contact.MakeEntry()

   Do contact.IncludeTelecom()
   Set telecom = contact.telecom.MakeEntry()
   Set telecom.system = "phone"
   Set telecom.value = "555-555-5555"
   Set telecom.use = "mobile"
   Do contact.telecom.add(telecom)
   Do patient.contact.add(contact)

   Set contactItr = patient.contact.get(0).telecom.iterator()
   While contactItr.hasNext() {
    Set contact = contactItr.next().value
    if contact.system = "phone" {
        Write !, contact.value
    }
   }

   Do patient.IncludeIdentifier()
   Set id = patient.identifier.MakeEntry()
   Set coding = ..MakeCoding("http://terminology.hl7.org/CodeSystem/v2-0203", "MR")
   Set id.type = coding
   Set id.value = ident
   Do patient.identifier.add(id)
   Set patientJSON = patient.toDao()



   Set service = ##class(HS.FHIRServer.Service).EnsureInstance(1)
   Do service.interactions.Add(patientJSON)
   Return $$$OK
}
讨论 (0)1
登录或注册以继续