Smile CDR v2024.05.PRE
On this page:

7.5.1Chained Searching And Sorting

 

FHIR chained searches allow for a search against a reference search parameter to 'chain' into the reference targets and search these targets for a given search criteria.

For example, consider the search: http://example.org/Encounter?patient.name=Simpson

This search returns any Encounter resources where the Encounter.patient reference points to a Patient resource satisfying the search name=Simpson.

In order to satisfy this search, a two-level SQL JOIN is required in order to satisfy both the reference and the string portions of the search. This search leverages two indexes created by the indexer:

  • A reference index satisfying the subject search parameter, associated with the Encounter resource.
  • A string index satisfying the name search parameter, associated with the Patient and Group resources.

Note that on this page we are talking about chains using normal resource references, as opposed to chains into contained resources. Chaining into contained resources is a powerful, but much less commonly used feature in the FHIR specification.

7.5.2Uplifted Refchains and Chaining Performance

 

If you are having performance issues when performing chained searches like the one above, a feature called Uplifted Refchains can be used to create a single index against the Encounter resource. Uplifted refchains promote chained search parameters to create a single index which includes both parts of the chain. In the example above this means:

  • A string index satisfying the subject.name search parameter, associated with the Encounter resource.

This can be very good for search performance, especially in cases where the second part of the chain (.name) matches a very large number of resources.

7.5.2.1Drawbacks

Using Uplifted Refchains has several drawbacks however, and it is important to consider them before enabling this feature:

  • Performance: while search and sort will be faster, write speed will be slower for the resource type containing the uplifted refchain. The target needs to be resolved, parsed, and the additional uplifted refchain index data must be written.
  • Correctness: Changes to the target data are not automatically reflected in the uplifted index copy, and chained search/sort may use stale data. For example, using the Encounter?subject.name=Simpson example above, the value of Simpson will be written to the index using the Patient's name at the time that the Encounter resource is written. If the Patient resource's name is subsequently changed to Flanders in an update, the new name will not be reflected in the chained search unless the Encounter resource is reindexed.

7.5.2.2Defining Uplifted Refchains

In order to use Uplifed Refchains, you must first enable Index Uplifted Refchains in your FHIR Storage (RDBMS) module configuration.

Then, the reference search parameter for the first part of the chain must be created or updated in order to add a new extension.

Continuing the example above, this means updating the Encounter:subject search parameter, creating it if it does not exist. Be careful not to create a second search parameter if you already have one defined for Encounter:subject. In this case, you must update the existing search parameter and add the new extension to it.

The extension has the following URL: https://smilecdr.com/fhir/ns/StructureDefinition/searchparameter-uplift-refchain

This extension has the following children:

  • code - Contains a code with the name of the chained search parameter to uplift.

An example follows:

{
   "resourceType": "SearchParameter",
   "id": "Encounter-subject",
   "extension": [
      {
         "url": "https://smilecdr.com/fhir/ns/StructureDefinition/searchparameter-uplift-refchain",
         "extension": [
            {
               "url": "code",
               "valueCode": "name"
            }
         ]
      }
   ],
   "url": "http://hl7.org/fhir/SearchParameter/Encounter-subject",
   "name": "subject",
   "status": "active",
   "code": "subject",
   "base": [
      "Encounter"
   ],
   "type": "reference",
   "expression": "Encounter.subject",
   "target": [
      "Group",
      "Patient"
   ]
}

7.5.3Document and Message Search Parameters

 

The FHIR standard defines several search parameters on the Bundle resource that are intended to be used for specialized Bundle types.

Name Type FHIRPath Expression
composition Reference Bundle.entry[0].resource as Composition
message Reference Bundle.entry[0].resource as MessageHeader

Unlike any other search parameters in the FHIR specification, these parameters use a FHIRPath expression that resolves to an embedded Resource (all other search parameters in the FHIR specification resolve to a datatype).

These parameters are only intended to be used as a part of a chained search expression, since it would not be meaningful to use them otherwise. For example, the following query could be used in order to use the composition search parameter to locate FHIR Documents stored on the server that are an International Patient Summary. In other words, this searches for Bundle resources where the first resource in the Bundle is a Composition, and that Composition has a Composition.type using LOINC code 60591-5. http://localhost:8000/Bundle?composition.type=http://loinc.org%7C60591-5

In order to use these search parameters, you must create a search parameter that includes the fully chained parameter value as the name and code values. In the example above, composition is the search parameter name, and type is the chain name. The fully chained parameter value is composition.type. A search parameter to support the query above would be:

{
  "resourceType": "SearchParameter",
  "id": "Bundle-composition-type",
  "url": "http://example.org/SearchParameter/Bundle-composition-type",
  "name": "composition.type",
  "status": "active",
  "code": "composition.type",
  "base": [ "Bundle" ],
  "type": "token",
  "expression": "Bundle.entry[0].resource.as(Composition).type"
}

You can also create search parameters that support a chained search against other resources in the Bundle. For example: http://localhost:8000/Bundle?composition.patient.identifier=http://example.org/mrn%7C12345

To support such a query, you should use a FHIRPath expression that fully resolves the intended value within the Bundle resource. You may use the resolve() function to resolve resources that are contained within the same Bundle. Note that when used in a SearchParameter expression, the resolve() function is not able to resolve resources outside of the resource being stored. A search parameter to support the query above would be:

{
  "resourceType": "SearchParameter",
  "id": "Bundle-composition-patient-identifier",
  "url": "http://example.org/SearchParameter/Bundle-composition-patient-identifier",
  "name": "composition.patient.identifier",
  "status": "active",
  "code": "composition.patient.identifier",
  "base": [ "Bundle" ],
  "type": "token",
  "expression": "Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier"
}

7.5.4Chained Sorting

 

The FHIR specification allows _sort expressions to use a comma-separated list of search parameter names in order to influence the sorting on search results.

Smile CDR extends this by allowing single-chained expressions as well. So for example, you can request a list of Encounter resources and sort them by the family name of the subject/patient of the Encounter by using the search shown in the example below. In this search, we are looking for all Encounter resources (typically additional search parameters would be used to limit the included Encounter resources), and sorting them by the value of the family search parameter on the Patient resource, where the Patient is referenced from the Encounter via the patient search parameter. http://example.org/Encounter?_sort=patient.family

Like chained search expressions, the first step in the chain must be a reference SearchParameter (SearchParameter.type = 'reference'). Unlike chained search expressions, only certain search parameter types can be used in the second part of the chain:

  • String
  • Date
  • Token

If the reference search parameter defines multiple target types, it must be qualified with the specific target type you want to use when sorting. For example, the Encounter:subject search parameter can refer to targets of type Patient or Group. The following expression will not work because the specific target type to use is not clear to the server. http://example.org/Encounter?_sort=subject.family

The following qualified expression adds a type qualifier and will work: http://example.org/Encounter?_sort=Patient:subject.family

7.5.4.1Chained Sort Performance

Because they involve sorting on an index that is only connected to the primary resource in the search by a two-level join, the performance of chained sort expressions can be highly variable.

In particular, this kind of sorting can be very slow if the search returns a large number of results (e.g. a search for Encounter?sort=patient.name where there is a very large number of Encounter resources and no additional search parameters are limiting the number of included resources).

In order to improve sorting performance when chained sorts are needed, an Uplifted Refchain can be defined on the SearchParameter. This index will be used for the sorting expression and can improve performance.