HL7/fhirpath.js

Use of $index always returns last element in list

jpnarkinsky opened this issue · 4 comments

The following fragment is expected to return '[0]' (the index of the element foo.bar.com.) Instead, it returns '[1]'. When used with longer arrays, it apparently always returns the index of the last element in the array.

> const fhirpath = require('fhirpath')
undefined
>     const resource = {
...       resourceType: 'Practitioner',
...       telecom: [{
.....         'use': 'work',
.....         'rank': 2,
.....         'value': 'foo.bar.com',
.....         'system': 'url',
.....       },
...       {
.....         'use': 'work',
.....         'rank': 1,
.....         'value': 'bar.foo.com',
.....         'system': 'url',
.....       }],
...     };
undefined
> fhirpath.evaluate(resource, `Practitioner.telecom.where(value='foo.bar.com')`)  # this returns the element at index 0
[ { use: 'work', rank: 2, value: 'foo.bar.com', system: 'url' } ]
> fhirpath.evaluate(resource, `Practitioner.telecom.where(value='foo.bar.com').$index`)  # this returns index 1
[ 1 ]
>  

Am I completely misundertanding the purpose of $index, or is this a bug? Any ideas would be appreciated since this is a show-stopper for us.

The behavior of $index outside of a expression passed into an function is not defined. The specification says, "If the function takes an expression as a parameter, the function will evaluate the expression passed for the parameter with respect to each of the items in the input collection. These expressions may refer to the special $this and $index elements, which represent the item from the input collection currently under evaluation, and its index in the collection, respectively."

In other words, you can do, ".where($index =1)", but you can't do ".where(...).$index."

@plynchnlm In that case, shouldn't something like this work?

Practitioner.telecom.where(value='foo.bar.com').select($index)

If so, it doesn't appear to work -- it always returns 0.

> fhirpath.evaluate(r, 'Practitioner.telecom')
[
  { use: 'work', rank: 2, value: 'foo.bar.com', system: 'url' },
  { use: 'work', rank: 1, value: 'bar.foo.com', system: 'url' }
]
> fhirpath.evaluate(r, "Practitioner.telecom.where(value = 'foo.bar.com')")
[ { use: 'work', rank: 2, value: 'foo.bar.com', system: 'url' } ]
> fhirpath.evaluate(r, "Practitioner.telecom.where(value = 'foo.bar.com').select($index)")
[ 0 ]
> fhirpath.evaluate(r, "Practitioner.telecom.where(value = 'bar.foo.com').select($index)")
[ 0 ]

Our objective is to get the index of the matching element (for our open source fhirpatch library). Any suggestions on a path that would accomplish that?

After the "where" function has run, you are left with an array of one element, so when the "select" call operates on that, the value of $index is zero.

The question of how to get the $index of a element matching some expression is an interesting one. I suggest you post that question on the fhirpath stream of chat.fhir.org.