Replies: 5 comments 6 replies
-
@rbrush What restrictions are inside |
Beta Was this translation helpful? Give feedback.
-
Here is a draft of minimized FHIRPath grammar https://gist.github.com/niquola/61703a2a83d6f851e4cb2a6c021f08ba |
Beta Was this translation helpful? Give feedback.
-
Some open questions and additional needs from today's working group meeting that we should expand to. Please feel free to add others as well. I'll highlight one as the biggest open question, and then list others:
Here are other open questions, but perhaps not as complicated as the first:
|
Beta Was this translation helpful? Give feedback.
-
Notes from our working group meeting on 4/28Revised BP flattening definition example:{
"view": "blood_pressure_with_dar",
"resource": "Observation",
"filters": [
"Observation.code.coding.exists(system='http://loinc.org' and code='85354-9')"
],
"vars": {
"component_sbp": "Observation.component.where(code.coding.exists(system='http://loinc.org' and code='8480-6')).first()",
"component_dbp": "Observation.component.where(code.coding.exists(system='http://loinc.org' and code='8462-4')).first()"
},
"fhirVersion": ["4.0.1", "5.0.0"], //optional
"columns": {
"id": "Observation.id",
"patient_id": "Observation.subject.getId()",
"effective_date_time": "Observation.effective.ofType(dateTime)",
"sbp_quantity_code": "%component_sbp.value.ofType(Quantity).system",
"sbp_quantity_code": "%component_sbp.value.ofType(Quantity).code",
"sbp_quantity_display": "%component_sbp.value.ofType(Quantity).unit",
"sbp_quantity_value": "%component_sbp.value.ofType(Quantity).value",
"sbp_has_dar": "%component_sbp.dataAbsentReason.exists()",
"dbp_quantity_system": "%component_dbp.value.ofType(Quantity).system",
"dbp_quantity_code": "%component_dbp.value.ofType(Quantity).code",
"dbp_quantity_display": "%component_dbp.value.ofType(Quantity).unit",
"dbp_quantity_value": "%component_dbp.value.ofType(Quantity).value",
"dbp_has_dar": "%component_dbp.dataAbsentReason.exists()"
}
} Discussion and open questions:
|
Beta Was this translation helpful? Give feedback.
-
I spent some time playing with this technology this weekend, and came up with some thoughts.
I am imagining scenarios where the software interpreting this model who issues
As an interesting side note - I created these JSON examples in VSCode running Copilot, and Copilot auto-generated the columns and relationships elements with those structures. The future is now. That's all I have for now. Looking forward to seeing you all at the connectathon. |
Beta Was this translation helpful? Give feedback.
-
This post explores some options for defining flattened FHIR tables via a subset of FHIRPath expressions. This is an exploration of options intended to start a discussion.
Possible requirements
A few possible requirements for this system:
A portable, unambiguous specification
Any good standard is unambiguous and portable between technology stacks, and this is no exception.
Build on an improved SQL-on-FHIR “level 0”, when available
This proposal builds on a proposed “level 0” representation of FHIR data in SQL databases that improves on the approach previously documented at https://github.com/FHIR/sql-on-fhir/blob/master/sql-on-fhir.md. For example, the “level 0” may hash ids, add raw id fields to FHIR reference types, or expand “date” types into start date/end date pairs. Users may query level 0 directly if needed, or use tabular views proposed here on top of it.
Ability to select from repeated structures based on field values
Flattened repeated structures in FHIR requires checking the content of those fields. For example, creating a table of patient home addresses requires checking that the address.use field is ‘home’. Similarly, a table with columns for systolic and diastolic blood pressures needs to check the Observation.component.code fields to select them properly.
Ability to filter based on value sets when creating a view.
Many useful FHIR queries rely heavily on value sets to identify needed resources. For instance, users may be interested in a table of statin meds for analysis, requiring a value set of statin medication codes to allow such a flattened view of statins. Therefore some form of valueset-based filter should be used to create the needed views.
Leverage existing standards whenever possible
Whenever practical we should avoid creating new standards and use existing approaches to these problems.
Support direct exports from data sources
Some users have limited analytic needs and only need views over a small subset of FHIR data that could be produced by a given system. Ideally a flattened FHIR definition could be interpreted by a FHIR service so only the needed subset of data is produced – whether directly in a tabular form or limited to the FHIR resources needed for the views.
Proposal: columns and filters with a subset of FHIRPath
One approach to the above would be to use a subset of FHIRPath to define flattened columns for use. Here’s a simple example showing a flattened table of home addresses.
The goal with these examples is not to fully define a spec, but rather to illustrate the approach for discussion.
Here’s another example that creates a simple table of LDL values. Notice this adds a “constraints” section that checks for a specific value set.
Subset of FHIRPath
Here is a working list of the subset of FHIRPath we might support for this:
where
function to select items in arrays (like the home address)equals
operator, primarily for use in the where function above.ofType
function to select the desired value type, as seen above.first
function. This is easily implemented as getting the first item in an array, and simplifies the output when users are looking for only a single value for a scalar column.memberOf
function to allow checking for value sets.We may consider additional FHIRPath expressions over time, but the above starting point will be able to handle many analytic workloads.
Cross-resource support explicitly out of scope
This possibility of including cross-resource joins as part of the flattened FHIR specification was mentioned, but tentatively ruled out. This is because once there are flattened FHIR tables, simply using SQL joins on top of them are flexible and reasonably portable between systems.
Translating FHIRPath to SQL
The ability to translate FHIRPath into SQL is central to this proposal. There are a couple of systems that have shown this is viable: Pathling and an open source Python library from Google.
A deeper exploration of FHIRPath to SQL translation can follow, but the above projects do so by recursively walking the FHIRPath parse tree and converting each sub-expression into an SQL expression – then assembling the full SQL expression as the logic unwinds that recursion.
I won’t fully detail the logic here, but consider this example of selecting the home postal code from a patient’s address:
The logic will find that postalCode comes from the address, and produce an SQL sub-expression like this:
From there we work back up the tree recursively, and encounter the where clause, so we translate that to SQL and add it to the UNNEST:
JSON-backed implementation options
The above example focuses on a FHIR encoding that uses first-class columns in databases, but some users may prefer to keep FHIR in JSON form in the database. We won’t go into that deeply here, but translation to JSONPath supported by some databases could be straightforward. For instance, this FHIRPath:
would translate to this JSONPath with a relatively straightforward traversal of the parse tree:
Challenges
There are a few challenges in translating FHIRPath to SQL that should be considered going forward:
Alternatives
There are a few alternatives we can consider, listed below. The notes below are incomplete, but we can follow up with more detailed analyses the pros and cons of these if they seem promising.
Transpile a standard SQL dialect
Tools like sqlglot can take standard ANSI SQL and translate it into a variety of SQL dialects, allowing for a portable specification. However, based on some limited exploration, there may not be a transpiler capable of handling the full nested and repeated structures seen in FHIR. For instance, UNNEST and LATERAL VIEW EXPLODE don’t seem fully supported, and the fact that not all databases support correlated subqueries to tap into nested data can lead to significantly different data structures. That said, deeper analysis could be justified here if there is interest in this approach.
Collections of DBT-like macros
It may also be possible to mitigate the variance in SQL dialects with an approach like DBT macros, with a distinct implementation of each macro. This may not be desirable since it ties the approach to DBT tooling rather than a portable standard.
Beta Was this translation helpful? Give feedback.
All reactions