Stream: fhirpath
Topic: Using `as` over a collection
Lee Surprenant (Nov 06 2019 at 18:11):
http://hl7.org/fhirpath/index.html#types says:
If there is more than one item in the input collection, the evaluator will throw an error.
Lee Surprenant (Nov 06 2019 at 18:12):
however, there are multiple search parameter expressions in fhir that use it over an element with cardinality > 1 (e.g. Observation.component.value as Quantity
where component can repeat)
Lee Surprenant (Nov 06 2019 at 18:13):
is this an issue with the fhirpath spec? or is it an issue with fhir's use of it?
Lee Surprenant (Nov 06 2019 at 18:14):
or is the guidance at http://hl7.org/fhirpath/index.html#types not applicable for as
when used this way? for example, maybe its only referring to as
the function?
Paul Lynch (Nov 06 2019 at 18:19):
What would be a use case where you would want to do Observation.component.value as Quantity
with multiple components?
Lee Surprenant (Nov 06 2019 at 18:29):
see component-value-quantity
at https://www.hl7.org/fhir/observation.html#search
Lee Surprenant (Nov 06 2019 at 18:30):
not sure about real-world use case for it...seems like normally you'd want to seach on the "composite" parameter
Lee Surprenant (Nov 06 2019 at 18:30):
but I assume the search parameter exists for a reason
Lee Surprenant (Nov 06 2019 at 18:35):
another example where as is used over a collection in fhir is the dom-3 constraint (but this one is pretty complicated):
description = "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", expression = "contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()"
Paul Lynch (Nov 06 2019 at 18:36):
I see. There is either a problem with the FHIRPath specification, or a problem with the "Expression" for the component-value-quantity search parameter.
Lee Surprenant (Nov 06 2019 at 18:36):
for that dom-3 example, just note the %resource.descendants().as(canonical)
i guess
John Timm (Nov 06 2019 at 18:42):
It's also worth mentioning that the FHIRPath specification does not document the as
an is
functions (only the operators). I think the FHIRPath specification should change to allow collections that have more than one item (to specifically support the search parameter extraction and constraints that use them that way).
Paul Lynch (Nov 06 2019 at 18:42):
http://build.fhir.org/ig/HL7/FHIRPath/branches/master/N1/index.html#types includes "as" and "is" functions, but they are deprecated.
Paul Lynch (Nov 06 2019 at 18:43):
@Bryn Rhodes ?
John Timm (Nov 06 2019 at 18:56):
Interesting. I wonder why they are deprecated. They are used a lot.
Bryn Rhodes (Nov 06 2019 at 18:58):
Yes, the FHIRPath spec defines the is and as operators as singleton operators; otherwise there is some ambiguity about the result. It appears though that for the as operator at least, at least one reference implementation doesn't respect that singleton-ness.
Bryn Rhodes (Nov 06 2019 at 18:59):
The is() and as() functions are deprecated because they are defined as operators. They are defined as operators because the arguments are type specifiers, a different syntactic category than expression.
Bryn Rhodes (Nov 06 2019 at 19:00):
(Either that, or that constraint has never been violated in practice).
John Timm (Nov 06 2019 at 21:25):
I would say there is evidence that as is used with non-singleton collections in some of the built-in FHIRPath expressions used within the FHIR specification (e.g. dom-3).
John Timm (Nov 06 2019 at 21:38):
Also, per the comment about the argument is a type specifier, I got around this by asking ANTLR for the text of the AST node instead of trying to evaluate the expression (like I would for qualified identifier).
Lee Surprenant (Nov 06 2019 at 21:41):
so i'm still wondering this: is it a fhirpath issue or a fhir issue?
Lee Surprenant (Nov 06 2019 at 21:42):
should I open a GForge ticket for it? should it start with fhir-i or fhirpath?
Lee Surprenant (Nov 06 2019 at 21:45):
per my current understanding and bryn's response, this would be a FHIR issue.
but clearly using as
to filter a collection down to just the elements of a given type is a very useful capability...is there something comparable for FHIR to use if it can't use as
in this way?
Lee Surprenant (Nov 06 2019 at 21:47):
maybe Observation.component.select(value as Quantity)
in this case?
Grahame Grieve (Nov 06 2019 at 22:43):
well. This works in my implementation. Clearly, the FHIR Path test cases don't test out the failure of this on a collection, since I do succeed on these implementations
Grahame Grieve (Nov 06 2019 at 22:44):
given the massive amount of work a technical correction represents (approximately a month of > 8hrs/day so far), I'm just not going to correct this right now
Grahame Grieve (Nov 06 2019 at 22:44):
so I'm not sure what the right resolution is. Take the first example
Grahame Grieve (Nov 06 2019 at 22:45):
Observation.component.value as Quantity
I think this is clear, at least, and what I'm trying to do seems reasonable to me - select all the Observation.component.value that are Quantities
Paul Lynch (Nov 06 2019 at 22:49):
Or that might be expected to include an assertion that all of the Observation.component.values are Quantities.
Grahame Grieve (Nov 06 2019 at 23:06):
as is not an assertion. things that fail as fall out
Paul Lynch (Nov 06 2019 at 23:08):
Oops-- yes you are right.
Bryn Rhodes (Nov 07 2019 at 06:57):
Agreed on the level of effort, it's trivial to characterize this as a clarification on as
behavior, given that at least one system behaves that way. And the behavior is reasonable for as
, though I would not say the same for is
; in the is
case, I think it's still ambiguous and should be treated as an error. So I'm hearing support for considering this a clarification on FHIRPath and submitting as a tracker there?
Grahame Grieve (Nov 07 2019 at 07:07):
I'd like that
Grahame Grieve (Nov 07 2019 at 07:07):
for as.
Grahame Grieve (Nov 07 2019 at 07:07):
is.. I don't know if I used it like that
Grahame Grieve (Nov 07 2019 at 07:08):
if the focus cardinality != 1, I return false from .is()
Lee Surprenant (Nov 07 2019 at 13:11):
I added a throw for cardinality != 1 for both as
and is
. This is how I found the issue with FHIR use of as
in the first place.
For is
, I havn't seen any such issue...I don't think FHIR is using that on collections with size > 1 and so I agree that one can stay as-is (no pun intended).
Lee Surprenant (Nov 07 2019 at 13:14):
However, it would be good to nail down the expected behavior of as
and is
when the left operand is an empty collection.
In our implementation, I had to stop throwing when the input collection to is
was empty, but instead of returning false we opted to return an empty collection in this case.
Lee Surprenant (Nov 07 2019 at 13:18):
The spec says:
If the left operand is a collection with a single item and the second operand is a type identifier, this operator returns true if the type of the left operand is the type specified in the second operand, or a subclass thereof. If the input value is not of the type, this operator returns false. If the identifier cannot be resolved to a valid type identifier, the evaluator will throw an error. If the input collections contains more than one item, the evaluator will throw an error. In all other cases this operator returns the empty collection.
So our interpretation was that an empty input collection would fall through to that last sentence (which matches a number of other functions) and this seems to be working well.
Lee Surprenant (Nov 07 2019 at 13:39):
I opened https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=25188 for this issue
Lee Surprenant (Nov 07 2019 at 19:20):
I also opened https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=25189 for the behavior of is
on an empty input collection, but I accidentally clicked submit before flagging it for FHIRPath...can someone please correct that?
Grahame Grieve (Nov 07 2019 at 20:11):
fixed
Last updated: Apr 12 2022 at 19:14 UTC