Skip to main content

FHIRPath

FHIRPath is a language, similar to XPath, that allows you to navigate a FHIR® resource to evaluate and extract data from its fields using a straightforward syntax that includes paths, functions, and operations. For example, you could evaluate whether the given name of a Patient contained a value: Patient.name.given.empty(). Or you could extract the value of the Patient resource’s telecom field, but only if offical is the value of its use field: Patient.telecom.where(use = 'official').

In FHIRPath, expressions are collection-based. Each function works on one input collection and each binary operator operates on two input collections, and the values returned by the expression are gathered into an output collection. Some functions and operations place constraints on the size of their input collections.

For complete details about FHIRPath including how to build an expression, see the HL7 FHIRPath specificationOpens in a new window. InterSystems supports a subset of the functions and operations that are defined in the specification.

Workflow

With InterSystems technology, the process of using FHIRPath to evaluate and extract data from a resource is straightforward:

Instantiate FHIRPath object, parse FHIRpath expression, evaluate a resource, and work with collection of results

The following sections provide details about each step in the workflow.

Instantiate HS.FHIRPath.API

The process of using FHIRPath to evaluate and extract data from a resource begins with calling HS.FHIRPath.API.getInstance()Opens in a new window. When you call this method, you must specify the FHIR package that corresponds to a version of FHIR. For example, if the resources you are evaluating conform to FHIR R4, the corresponding package ID is currently hl7.fhir.r4.core@4.0.1. In this case, instantiating HS.FHIRPath.API would look like:

 set fhirPathAPI = ##class(HS.FHIRPath.API).getInstance($lb("hl7.fhir.r4.core@4.0.1"))
Copy code to clipboard

You can obtain the IDs of the currently loaded packages using the Management Portal or ObjectScript:

  • Management Portal — Navigate to Home > Health > MyFHIRNamespace > FHIR Configuration, and select the Package Configuration card. The package ID is obtained by appending the @ symbol and version number to the name of the package. For example, the ID of the following package is hl7.fhir.r4.core@4.0.1:

    name of FHIR package: hl7.fhir.r4.core

  • ObjectScript — To list package IDs programmatically, see Listing Available Packages.

The HS.FHIRPath.API object includes the methods used to parse FHIRPath expressions and evaluate resources. This object is also included as a property on the HS.FHIRMeta.API object under the FHIRPathAPI property.

Parse the FHIRPath Expression

Once you have instantiated the HS.FHIRPath.API object, you are ready to parse the FHIRPath expression. The method that parses the expression, HS.FHIRPath.API.parse()Opens in a new window, returns a tree structure that is used by the methods that evaluate a resource. For example, assuming you have an object named fhirPathAPI instantiated as shown in the previous section:

 set tree = fhirPathAPI.parse("name.given.empty()")
Copy code to clipboard

Evaluate the Resource

Once you have parsed the FHIRPath expression, you can use its tree structure to evaluate or extract data from a resource. Two evaluation methods are available:

In both cases, the resource being evaluated is passed into the method as a dynamic object. The tree that was returned by the parse() method is also passed as an argument. For example:

 set tree = fhirPathAPI.parse("name.given.empty()")
 // myResource is a dynamic object
 do fhirPathAPI.evaluate(myResource, tree, .OUTPUT)
 set DynArray = fhirPathAPI.evaluateToJson(myResource, tree)
Copy code to clipboard

An additional method, HS.FHIRPath.API.evaluateArray()Opens in a new window, can be used to parse the multidimensional array returned by the evalaute() method.

Work with the Results

While working with results in a dynamic array that is produced by evaluateToJson() has its benefits, the multidimensional array produced by evaluate() contains additional information that is not otherwise available. The following provides a guide to the data in the multidimensional array, assuming that your response to evaluate() was returned in a variable named OUTPUT.

Node Description
OUTPUT Number of nodes in the array that contain values.
OUTPUT(n) Value of the nth element of the array.
OUTPUT(n,"t") Data type of the nth element in the array, including identifying FHIR data types.

You can further parse the returned multidimensional array using the evaluateArray() method.

By contrast. when using the evaluateToJson() method to produce a dynamic array, you can determine whether the data type is a string, boolean, number, or object from looking at the values in the array, but you cannot determine the FHIR data type.

Workflow Example: evaluate() Method

This example includes the resource being evaluated, the ObjectScript needed to evaluate the resource, and a look at the multidimensional array produced by the evaluation.

Sample Resource
 set myResource = {
   "resourceType":"Patient",
   "telecom": [
     {
       "system": "phone",
       "value": "(03) 5555 6473",
       "use": "official"
    },
    {
      "system": "phone",
      "value": "(03) 5555 6473",
      "use": "home"
    },
    {
      "system": "email",
      "value": "myName@email.com",
      "use": "official"
     }
   ]
 }
Copy code to clipboard
Extracting Data from the Resource
 set fhirVersion = $lb("hl7.fhir.r4.core@4.0.1")
 set fhirPathAPI = ##class(HS.FHIRPath.API).getInstance(fhirVersion)
 set tree = fhirPathAPI.parse("telecom.where(use = 'official')")
 do fhirPathAPI.evaluate(myResource, tree, .OUTPUT)
Copy code to clipboard
Viewing the Multidimensional Array

If you used the zw OUTPUT command in the InterSystems Terminal to view the multidimensional array returned by evaluate(), the result would be:

OUTPUT=2
OUTPUT(1)={"system":"phone","value":"(03) 5555 6473","use":"official"}
OUTPUT(1,"t")="ContactPoint"
OUTPUT(2)={"system":"email","value":"myName@email.com","use":"official"}
OUTPUT(2,"t")="ContactPoint"
Copy code to clipboard

Notice that the values are identified as a ContactPoint FHIR data type.

Workflow Example: evaluateArray() Method

This example takes the multidimensional array produced by the evaluation in the evaluate() example above as input and demonstrates the ObjectScript needed to evaluate the resulting array, and looks at the multidimensional array produced by the evaluation.

Extracting Data from the Output Array
 Merge INPUT = OUTPUT
 Kill OUTPUT

 Set tree = fhirPathAPI.parse("ContactPoint.value")

 do fhirPathAPI.evaluateArray(.INPUT, tree, .OUTPUT)
Copy code to clipboard
Viewing the Multidimensional Array

If you used the zw OUTPUT command in the InterSystems Terminal to view the multidimensional array returned by evaluateArray(), the result would be:

OUTPUT=2
OUTPUT(1)="(03) 5555 6473"
OUTPUT(1,"t")="string"
OUTPUT(2)=”myName@email.com"
OUTPUT(2,"t")="string"
Copy code to clipboard

Notice that the values are identified by their ObjectScript data type (string, boolean, number, or object).

Workflow Example: evaluateToJson() Method

This example includes the resource being evaluated, the ObjectScript needed to evaluate the resource, and a look at the dynamic array produced by the evaluation.

Sample Resource
 set myResource = {
   "resourceType":"Patient",
   "name": [
     {
       "family": "Cooper",
       "given": [
         "James",
         "Fenimore"
       ]
     }]
 }
Copy code to clipboard
Evaluating the Resource
 set fhirVersion = $lb("hl7.fhir.r4.core@4.0.1")
 set fhirPathAPI = ##class(HS.FHIRPath.API).getInstance(fhirVersion)
 set tree = fhirPathAPI.parse("name.given.empty()")
 set dynArray = fhirPathAPI.evaluateToJson(myResource, tree)
Copy code to clipboard
Viewing the Dynamic Array

If you used the zw dynArray command in the InterSystems Terminal to view the dynamic array, the result would be:

dynArray=[false]
Copy code to clipboard

Functions

The FHIRPath specification defines a wide range of functions that can be used in an expression. InterSystems supports a subset of those functions.

Supported FHIRPath Functions
Function Example
[ ] (index)Opens in a new window Practitioner.name[1]
aggregateOpens in a new window item.factor.aggregate($total+$this,0)
asOpens in a new window Condition.abatement.as(string)
emptyOpens in a new window name.empty()
existsOpens in a new window Patient.telecom.exists(system = 'phone')
extensionOpens in a new window extension('http://intersystems.com/fhir/extn/sda3/lib/code-table-detail-care-provider-description').value as string
iifOpens in a new window iif(1=1,2,3)
isOpens in a new window Condition.abatement.is(dateTime)
notOpens in a new window gender.not()
resolveOpens in a new window Organization.partOf.resolve()
unionOpens in a new window Practitioner.name.family.union(Practitioner.id)
whereOpens in a new window Patient.telecom.where(use = 'official')

Operations

The FHIRPath specification defines a wide range of operations that can be used in an expression. InterSystems supports a subset of those operations.

Supported FHIRPath Operations
Operation Example
+ (addition)Opens in a new window
8 + 3
5 seconds + 3 seconds
'string1' + ' and ' + 'string2'
& (string concatenation)Opens in a new window 'string1' & ' and ' & 'string2'
= (equals)Opens in a new window
Practitioner.name[0].family = 'Cooper'
Practitioner.meta.versionId = 10
!= (not equals)Opens in a new window Practitioner.name[1].family != 'Smith'
| (union collections)Opens in a new window Practitioner.name.family | Practitioner.id
andOpens in a new window true and false
asOpens in a new window See implementation notes.
impliesOpens in a new window Patient.name.given.exists() implies Patient.name.family.exists()
isOpens in a new window Practitioner.name[0] is HumanName
orOpens in a new window true or false
xorOpens in a new window true xor false
Implementation Notes for as

According to the FHIRPath specification, the left operand of the asOpens in a new window operation must be a collection with a single item. However, the InterSystems implementation of FHIRPath allows this collection to have multiple values. For example, suppose you have an Observation with multiple extensions that reference a Patient. With the InterSystems implementation of FHIRPath, the following expression would still be valid: extension.value as Reference.

Improving Performance

InterSystems provides an in-memory cache that can store parsed FHIRPath expressions, improving performance when you have a set of expressions that are repeated frequently. Once the cache is enabled, tree structures produced by the parse() method are stored until the cache is cleared.

To enable the in-memory cache, call:

do fhirPathAPI.enableCache(1)
Copy code to clipboard

To disable the cache, call:

do fhirPathAPI.enableCache(0)
Copy code to clipboard
FeedbackOpens in a new window