Examples¶
The pack ships one shelf, fhir, which an instance lists under its examples once the pack is
installed. Every document but fhir-fhirpath-plain-json talks to a local HAPI FHIR server, never a
public one, because most of them write. Start one, and a second for the copy:
docker run -d --name fhir-source -p 8090:8080 hapiproject/hapi:v8.12.0-2
docker run -d --name fhir-target -p 8091:8080 hapiproject/hapi:v8.12.0-2
| Document | What it does |
|---|---|
fhir-read |
Read one resource by its type and id. |
fhir-search-paged |
Search one type, following next links for at most five pages. |
fhir-create-if-none-exist |
Create a patient unless one with the same identifier is already there. |
fhir-update-by-identifier |
Write a patient over the one with the same identifier, or create it. |
fhir-update-by-id |
Write a patient at a known id, creating it there the first time. |
fhir-patch |
Change part of a patient with a JSON Patch and a FHIRPath Patch. |
fhir-delete-test-data |
Delete test patients by a search, bounded by max, and one by its id. |
fhir-operation-everything |
Invoke a patient's $everything, a $validate and a $expand. |
fhir-copy-on-schedule |
Copy patients and their observations from one server to another, nightly. |
fhir-copy-page-by-page |
Copy patients and observations to another server, a transaction per page. |
fhir-fhirpath-high-readings |
Find body weights over a limit, and the patients they belong to, with FHIRPath. |
fhir-fhirpath-plain-json |
Filter, map and reshape records that are not FHIR, with no server. |
fhir-validate-before-copy |
Validate a search's resources, and copy them only if they are sound. |
fhir-measure-heavy-adults |
Score heavy adults as a proportion of adults, with CQL, into a MeasureReport. |
FHIR to FHIR on a schedule¶
fhir-copy-on-schedule is the pack's first flagship. One search reads every patient on the
source with the observations that point at them (_revinclude=Observation:subject), and one
transaction writes them to the target:
steps:
find:
block: fhir.search
config:
connection: fhir-source
resource_type: Patient
params:
_revinclude: Observation:subject
_count: "100"
max_pages: 20
copy:
block: fhir.transaction
depends_on: [find]
config:
connection: fhir-target
bundle: ${steps.find.output.bundle}
The transaction rewrites each Observation.subject from the source's Patient/17 to the
patient's urn:uuid, and writes every resource as a conditional update on its identifier. The
source's ids never reach the target, and the second night writes over what the first created:
created is zero and updated counts everything.
A page at a time¶
fhir-copy-page-by-page copies the same search with emit: pages, so the search hands on one
Bundle per page and the copy fans out over them, one transaction per page:
steps:
find:
block: fhir.search
config:
connection: fhir-source
resource_type: Patient
params:
_revinclude: Observation:subject
_count: "50"
max_pages: 100
emit: pages
copy:
block: fhir.transaction
depends_on: [find]
for_each: ${steps.find.output.bundles}
items: continue
config:
connection: fhir-target
bundle: ${item}
Each page is its own item with its own status and retry, and one refused page fails its own
item rather than the copy. emit: resources hands on one resource per item instead, for a
step such as fhir.update that writes one at a time.
A complete project around the copy, with a verify.sh that starts two HAPI servers, seeds one, copies,
and asserts the copy, is fhir-to-fhir in
dirigent-examples.
FHIRPath on plain JSON¶
fhir-fhirpath-plain-json runs the three FHIRPath verbs over records that are not FHIR, written
inline, with no connection and nothing else running:
filter.fhirpath keeps the cities over the limit, map.fhirpath builds a line from each and reads
a hyphenated key in backticks, and transform.fhirpath walks into one object. The
block reference says what to expect on data with no schema
behind it.