Stream: cql
Topic: How to reference specific repeating element?
John Silva (Apr 09 2021 at 12:30):
New to CQL so sorry if this is a 'newbie question'.
If one wants to create a CQL expression to reference a specific entry in an array parameter, e.g. the identifier array element type marked as 'MR' (MRN) or use marked as 'official', how would that be done? I'm suspecting it could be done with this, but haven't tried it yet: Patient.identifier.where(type = 'MR').value
or Patiient.identifier.where(use = 'official').value
. (the MR example is probably more complicated because the MR is in the coding[].code element)
BTW, I tried some of this using an online FHIRpath tester tool but I'm not sure how closely CQL expressions follow FHIRpath syntax.
Update: this seems to work with the FHIRpath tool but is it correct CQL syntax:
Practitioner.identifier.where(type.coding.code='TAX').value
Chris Moesel (Apr 09 2021 at 13:41):
@John Silva -- the answer is mostly... "it depends". It assumes an available Practitioner
definition and uses several CQL language options. These options may or may not be allowed/supported depending on your situation (what translator you're using, what options are enabled on it, etc).
- Since the phrase starts with
Practitioner
, this only works if you have defined aPractitioner
expression or are working in aPractitioner
context that provides aPractitioner
expression for you. - Since
Practitioner.identifier
is an array and you directly access.value
on it (after filtering), you are using an option called Path Traversal, which basically implies the iteration and collects the tail values for you. This is an option in CQL that was only added later in the spec, and mainly to align w/ FHIRPath. (BTW -- this is also happening withtype.coding.code = 'TAX'
, sincetype.coding
is an array). - The use of
.where(...)
employs the Method Invocation option (or "fluent" syntax). Like path traversal, this is also an option in CQL that was only added later in the spec, and mainly to align w/ FHIRPath.
So, yes, that is technically valid CQL assuming all the necessary options are enabled (and Practitioner
is defined). But I'm not sure that it's common in CQL. That however, may just be because these features are newer (and optional) aspects of the language. I'd be interested in what @Bryn Rhodes has to say about this. Bryn, do you encourage CQL developers to utilize there FHIRPath syntaxes in CDS and/or eCQM development?
BTW -- if you wanted to write CQL that avoids those particular options, it would look something like this:
Practitioner.identifier PI
where exists(
PI.type.coding C where C.code.value = 'TAX'
)
return PI.value
So, as you can see, those FHIRPath syntaxes do make things a little tidier (as long as the author understands what they're actually doing).
Bryn Rhodes (Apr 09 2021 at 15:42):
@Chris Moesel , @John Silva , yes, this is supported with the default options for the translator, you actually have to explicitly disable this functionality if you _don't_ want it supported:
https://github.com/cqframework/clinical_quality_language/blob/master/Src/java/cql-to-elm/OVERVIEW.md#usage
Bryn Rhodes (Apr 09 2021 at 15:45):
The translator will actually expand the FHIRPath syntax to use queries in the ELM, so that existing ELM engines _should_ be able to support it already. The X.where(<condition>)
for example, translates to X $this where <condition>
. Translation semantics for FHIRPath are specified in this appendix: https://cql.hl7.org/16-i-fhirpathtranslation.html
Bryn Rhodes (Apr 09 2021 at 15:47):
I will note that CQL developed for eCQMs specifically disables method invocation, so we don't see that in CQL for eCQMs, though that is being considered for use in the FHIR space, specifically to ensure FHIRPath expressions can be used without restrictions.
John Silva (Apr 09 2021 at 16:27):
We're using this CQL library; https://github.com/cqframework/clinical_quality_language -- I'll have to look at it's documentation to see if it supports this FHIIRpath expression syntax. @Chris Moesel - if not I'll try the syntax you mentioned, thanks!
(The interesting thing is that this comes from the fact that there is a profile on Questionnaire that specifies using CQL expressions rather than FHIRpath -- which is another discussion.)
John Silva (Apr 12 2021 at 15:37):
A related question:
I'm trying to extract the string value of the Practitioner.identifier[] array for the value where the type.coding.code is 'TAX'. I've tried this expression, which works in FHIRpath but not in CQL:
Practitioner.identifier.where(type.coding.code='TAX').value.first()
@Bryn Rhodes - would this FHIRpath expression be expected to work in CQL framework engine?)
If I use the expression syntax @Chris Moesel suggested it returns the value but as an array value, e.g. [12345]
Practitioner.identifier PI
where exists(
PI.type.coding C where C.code.value = 'TAX'
)
return PI.value
I tried this PI.value.first()
and that causing an exception in the CQF Ruler engine.
Alexander Kiel (Apr 12 2021 at 18:24):
You can use First.
Also Equivalent should work with CodeableConcept:
First(Practitioner.identifier PI where PI.type ~ Code 'TAX' from <system> return PI.value)
John Silva (Apr 12 2021 at 22:16):
@Alexander Kiel - thanks; that worked! I wonder if the FHIRpath syntax is supposed to work with the CQL framework code (or not)?
Bryn Rhodes (Apr 12 2021 at 22:56):
@John Silva , that syntax does work in the Atom plugin and evaluates, so it _should_ work in the ruler (same component), but it sounds like there's an issue there. What version of the ruler are you running? Just the latest?
John Silva (Apr 13 2021 at 00:22):
We're installing from this docker version: contentgroup/cqf-ruler. (I think we've deployed 'latest' but I'll check with our DevOps guy)
If I query the CapabilityStatement on the deployed HAPI server with CQF Ruler it reports:
` "software": {
"extension": [ {
"url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-softwareModule",
"extension": [ {
"url": "name",
"valueString": "CQF Ruler FHIR R4 Server"
}, {
"url": "version",
"valueString": "0.4.1"
} ]
} ],
'
Lloyd McKenzie (Apr 14 2021 at 04:14):
Be very cautious about using first when the data element doesn't define any semantics to sort order. Looking for first(given) is fine, because 'given' has a defined order. However first(name.given) would not be ok, because there's no order to the list of names and you're not allowed to count on particular names being first - and it's exceptionally bad practice for IGs to impose an order where it has no meaning. In these cases saying first() is essentially saying "grab one at random" - which is fine so long as there's no incentive for systems to try to make sure that a particular value happens to actually be first.
Alexander Kiel (Apr 14 2021 at 11:11):
@Lloyd McKenzie You are right. In the example of @John Silva , he linked to get the value of an identifier with a specific type. Normally, I suspect, that every resource will have only one such identifier. One could use singleton from to ensure that one doesn't pick a random element and enforce one identifier per type in the profiles.
John Silva (Apr 14 2021 at 11:20):
Thanks @Alexander Kiel and @Lloyd McKenzie Yes, I saw the 'disclaimer' about using First() or .first() in FHIRpath.. However, in our case we have (expect) only a single instance of the identifier repeat that matches the type code we're looking for though, that being said, it is still possible in our example, to have more than one TIN (Tax ID Number) for different jurisdictions, e.g. TIN for NY and another for VT, etc. So, I using the singleton() expression would be much better. However, in the case where there are multiple matches for TIN, I suppose it would be best left to pass the array of results back to the UI layer and let that determine how to display them to the user.
Last updated: Apr 12 2022 at 19:14 UTC