简而言之:InterSystems IRIS for Health 允许开发人员直接在后端 ObjectScript 例程中执行 FHIR CRUD 操作,而无需依赖 HTTP REST 层。通过使用 HS.FHIRServer.Service,开发人员可以创建服务上下文、构建动态查询、验证模式,并高效地检索 FHIR 资源。
传统的 FHIR 实现通常通过 HTTP/REST 管道处理请求。本文探讨了绕过该层、直接在 IRIS 后端执行 FHIR 操作时的情况,重点介绍了该方法涉及的架构、服务上下文、查询处理、验证和资源访问。
本文适用对象:本指南专为InterSystems IRIS for Health、HealthShare 和 Health Connect 开发人员,以及需要在不依赖外部 HTTP 端点的情况下,直接在后端 ObjectScript 例程中执行低开销 FHIR 操作的医疗信息学工程师而设计。
核心架构:标准流程与编程执行
部署在 InterSystems IRIS for Health、HealthShare 和 Health Connect 上的标准 FHIR 实现,依赖于通过 REST 应用层映射到 HS.FHIRServer.Service 的入站 HTTP 管道。 在此标准 Web 架构中,客户端应用程序通过 HTTP/HTTPS 传输请求;系统会验证安全令牌、解析请求负载,并将操作委托给存储库实现,以支持创建、读取、更新和删除(CRUD)范式以及专门的搜索功能。
通过完全绕过标准 Web 服务器分发层,ObjectScript 例程可以实例化后端服务上下文,并直接与 InterSystems IRIS FHIR 存储库的核心引擎室进行交互。 这种方法使开发人员能够构建本机查询对象、管理排序参数、验证模式,并以最高性能和精确的控制来运行存储级搜索或直接读取记录。
-
GET:用于读取单个资源 (GET [base]/Patient/123) 或使用查询过滤器搜索集合(GET [base]/Patient?gender=male&birthdate=ge1980-01-01)。 -
POST:用于创建一个全新的资源(POST [base]/Patient)。 -
PUT:用于更新现有资源,或根据标识符(PUT [base]/Patient/123)对其进行更新或插入(upsert)。 -
DELETE:用于删除或归档一条记录(DELETE [base]/Patient/123)。
当你在 GET 请求中加入查询参数时,就是在告诉服务器如何对数据进行切片和筛选。 然而,当你脱离浏览器或 Postman 时,IRIS 如何通过编程方式处理这些参数?与其完全依赖外部的 HTTP REST 层,不如使用 HS.FHIRServer.Service 直接在 IRIS 后端执行 FHIR 操作。
通过编程方式构建查询参数
在内部执行高级搜索时,规范地管理查询参数对于防止查询格式错误以及通过 JsonAdvSQL 执行引擎确保最佳性能至关重要。InterSystems 专门为此提供了 HS.FHIRServer.API.Data.QueryParameters。 根据数据来源的不同,您可以通过以下两种主要方法来构建并填充该对象:
· 方法 A:通过AddParameter() 手动构建: 如果您在应用程序逻辑中动态构建编程搜索条件(例如,根据内部业务规则、自定义 UI 中的用户选择或工作流状态构建查询),则应直接实例化 QueryParameters 类,并使用 AddParameter() 方法逐个添加过滤条件。 这种方法使您能够在查询到达 IRIS 存储层之前,对各个参数的名称、修饰符、前缀和值进行绝对控制。
· 方法 B:通过CreateFromQueryString() 从查询字符串进行解析:在处理原始 HTTP 请求时,您无需手动解析 URL 参数。InterSystems IRIS 在查询参数处理程序类中提供了一个原生实用方法——CreateFromQueryString()——可无缝地自动完成此转换。
通过编程方式对数据进行排序和链接
高级搜索需要通过显式参数配置,对结果排序和相关临床记录进行精确控制。
· 自动方式:在构建标准 FHIR 应用程序时,开发人员通常依赖传入的 REST URL。客户端可能会请求按最后更新日期降序排序的患者列表:GET [base]/Patient?gender=female&_sort=-_lastUpdated。 当您将此字符串传递给 HS.FHIRServer.API.Data.QueryParameters.CreateFromQueryString() 时,IRIS 会自动解析出 _sort 参数。
· 手动方式:如果您未使用 URL 查询字符串,或者希望在自定义交互类中拦截请求并强制采用特定的排序顺序(无论用户请求什么),则可以手动构建 .tSortKeys。 无需依赖字符串解析器,您可以在 ObjectScript 中显式构建排序数组。
· 正向链接(_include):它们沿着匹配资源向外的引用,提取相关实体(例如,搜索 MedicationRequest 资源并包含被引用的 Practitioner 或 Patient [MedicationRequest:patient])。
· 反向链接(_revinclude):它们从指向匹配资源的其他资源开始,向后追踪引用关系(例如,搜索“Patient”并提取所有引用该特定患者 ID 的“Observation”或“Encounter”记录 [Observation:patient])。
技术参考与实现代码示例
以下 ObjectScript 代码块演示了如何在 InterSystems IRIS 内部直接执行这些程序化工作流:
手动参数构建:
ClassMethod CreateParamsManually() As HS.FHIRServer.API.Data.QueryParameters
{
Set params = ##class(HS.FHIRServer.API.Data.QueryParameters).%New()
// Equivalent to filtering by ?gender=male
Do params.AddParameter("gender", "male")
// Equivalent to filtering by ?birthdate=ge1980-01-01
Do params.AddParameter("birthdate", "ge1980-01-01")
Quit params
}从查询字符串中解析:
ClassMethod CreateParamsFromString() As HS.FHIRServer.API.Data.QueryParameters
{
Set queryString = "gender=male&name=Smith"
// Set tQueryString = "patient=123&date=ge2026-01-01&_include=Observation:patient&_count=50"
// Automatically handles keys, values, prefixes (like 'ge'), and modifiers
Set params = ##class(HS.FHIRServer.API.Data.QueryParameters).CreateFromQueryString(queryString)
Return params
}通过 FindSearchParam 验证模式元数据:为防止因无效查询条件或资源-属性不匹配导致的运行时错误,应在执行前检查活动模式元数据。tStrategy.Schema.FindSearchParam(pResourceType, pParamName) 充当安全检查机制。
ClassMethod ValidateSearchParameter(pStrategy As HS.FHIRServer.Storage.JsonStrategy, pResourceType As %String, pParamName As %String) As %Boolean
{
// Evaluates if the parameter is valid for the specified resource in the active FHIR version schema
Set searchParam = pStrategy.Schema.FindSearchParam(pResourceType, pParamName)
If $IsObject(searchParam) {
Write "Parameter '", pParamName, "' is valid for resource '", pResourceType, "'.", !
Quit 1
}
Write "Invalid search parameter for this resource schema.", !
Quit 0
}针对交互引擎的直接搜索执行:
ClassMethod ExecuteDirectSearch(pAppKey As %String) As %Status
{
Set tSC = $$$OK
Try {
// Instantiate the FHIR Service, which contains the strategy and interactions objects
Set fhirService = ##class(HS.FHIRServer.Service).EnsureInstance(pAppKey)
// Access the underlying interactions engine through the strategy
Set tInteractions = fhirService.Strategy.GetInteractions()
// Reusing our query parameter builder
Set tParams = ##class(HS.FHIRServer.API.Data.QueryParameters).CreateFromQueryString("gender=male")
// Execute the Search method directly against the Interactions class
// Parameters: (ResourceType, Compartment, CompartmentId, QueryParameters, .SortKeys)
Set tSearchResult = tInteractions.Search("Patient", "", "", tParams, .tSortKeys)
// Iterate through the search results object
Write "Total matches found: ", tSearchResult.Total, !
// Loop through matching resource IDs or entries
While tSearchResult.Next(.tId, .tResourceJson, .tStatusCode) {
Write "Patient ID: ", tId, " | Details: ", tResourceJson.%ToJSON(), !
}
} Catch tException {
Set tSC = tException.AsStatus()
Write "Error during search: ", $System.Status.GetErrorText(tSC), !
}
Quit tSC
}通过 .Read() 直接检索资源:HS.FHIRServer.Storage.JsonAdvSQL.Interactions 上的 Read() 方法是核心编程功能,负责直接从存储库存储层获取特定单个 FHIR 资源的 JSON 数据,而无需运行搜索索引。
Set pResourceType = "Patient"
Set resourceId = "1"
// Retrieve the resource as a %DynamicObject directly using interactions.Read()
Set tInteractions = fhirService.Strategy.GetInteractions()
Set resourceString = tInteractions.Read(pResourceType, resourceId)
Write "Patient ID: ", resourceId, " | Resource Data retrieved successfully.", !应避免的常见错误
· 绕过模式验证:在执行动态查询前跳过对 FindSearchParam() 的调用,这可能导致当属性与当前有效的 FHIR 资源模式版本不匹配时,引发未处理的运行时异常。
· 硬编码 REST 依赖关系:强制内部微服务或批处理引擎通过本地回环 HTTP 请求进行路由,而非在 ObjectScript 中直接调用 HS.FHIRServer.Service 和 GetInteractions()。
· 结果遍历不当:在遍历 HS.FHIRServer.Util.SearchResult 对象循环时,未能正确评估结果状态码,或使用了错误的属性查找。
常见问题解答 (FAQ)
问:是否可以在不发送 HTTP 服务器请求的情况下执行 FHIR 查询?
答:可以。通过实例化 HS.FHIRServer.Service 并提取交互引擎,ObjectScript 代码可以在内存中完全执行搜索和读取记录。
问:如何通过编程方式添加 _include 参数?
答:在 QueryParameters 实例上调用 AddParameter() 方法,将 _include 作为键,目标引用路径(例如 Observation:subject)作为值传入。
问:HS.FHIRServer.API.Data.QueryParameters 的用途是什么?
A: 它提供了一种结构化的机制,可在通过 JsonAdvSQL 存储层执行之前,以规范的方式构建、解析和封装查询条件、修饰符和前缀。
问:.Read() 与 .Search() 有何区别?
A: Read() 接受显式的资源类型和逻辑 ID,可立即以 %DynamicObject 形式检索单条记录;而 Search() 则对资源集合进行多参数过滤评估。
问:如何在没有 URL 字符串的情况下处理自定义排序?
A:您可以结合通过 tStrategy.Schema.FindSearchParam() 获取的模式定义,使用 .tSortKeys 手动定义排序数组。
问:为什么在程序化执行过程中需要进行模式验证?
A:这可确保搜索键、属性及修饰符映射符合当前有效的 FHIR 配置文件定义,从而防止执行错误。
实用建议
在提取交互引擎之前,请务必使用 HS.FHIRServer.Service.EnsureInstance(pAppKey) 初始化运行时上下文。处理传入的文本映射时,请使用 CreateFromQueryString(),并通过 FindSearchParam 实现模式验证检查,以确保后端集成稳健且无误。
结论
通过绕过标准的 REST 路由并以编程方式调用 InterSystems IRIS FHIR 交互引擎,开发人员可以以低开销的方式直接访问核心存储库。 利用手动查询参数进行搜索,并使用 Read() 方法进行定向资源检索,可提供高性能后端集成和自定义业务逻辑所需的最快速度、最高精度和最大的架构灵活性。