5.3.1FHIR Search: References and Includes

 

FHIR resources will typically refer to each other, forming a web of related and referenced resources.

Resources refer to each other using the Reference datatype, and can take several forms:

  • A relative reference, which takes the form "[resourceType]/[id]" and refers to another resource available through the same FHIR endpoint. This is by far the most common form of reference in real world applications.
  • An absolute reference, which takes the form "http(s)://[baseUrl]/[resourceType]/[id]".
  • An internal fragment reference to a contained resource (see below).

A simple example of a Patient resource with a reference to the Organization which manages the record is shown below:

{
   "resourceType": "Patient",
   "id": "example",
   "name": [ {
      "family": "Jones",
      "given": [ "David" ]
   } ],
   "managingOrganization": {
      "reference": "Organization/acme"
   }
}

The corresponding Organization is shown below:

{
   "resourceType": "Organization",
   "id": "acme",
   "name": "ACME Corporation"
}

Most references will only point in one direction. In other words, Patient contains a reference to its Organization, but Organization does not contain a reference to its patient.

5.3.2References Example

 

The following example shows a collection of resources with various references. This data will be used for all of the examples on the rest of this page.

Selected search parameters are also shown for each resource, using the form: name (type): path

Example Data

5.3.3Searching By Reference

 

FHIR searches can be used to find resources which refer to other resources. For example, the following search finds any Observation resources which have patient P1 as a subject: http://localhost:8000/Observation?subject=Patient/P1

Results: The search above will return the following resource: Observation/O1.

Searches may be performed using any search parameter with a parameter type of reference. For example, see the FHIR Patient Resource Default Search Parameters to see what is available out of the box. You can also create Custom Search Parameters.

5.3.4Chained References

 

FHIR also supports a search syntax called chaining, where you can find resources that refer to other resources, but using a property of the other resource that isn't the resource ID. This syntax takes the following form:

[resourceType]?[reference search parameter].[search parameter on reference target]=[value]

For example, suppose you wish to find all Observation resources belonging to a specific patient, but you have only the patient's identifier, not their ID. You can perform this search by searching for Observations using the subject search parameter, but then chaining on the Patient's identifier search parameter. This is shown in the example below: http://localhost:8000/Observation?subject.identifier=http://ids|0001

Results: The search above will return the following resource: Observation/O1

5.3.4.1Adding a Chain Type (Always Recommended)

If you know the target type of the reference, it is possible to include it and improve the specificity of the search. You can do this by appending :[resourceType] before the dot. For example, the following search fetches Observations with a Patient subject named "smith". http://localhost:8000/Observation?subject:Patient.name=smith

This can be very helpful in terms of improving performance of this query, so you should always include the type of the target if you know it. This is the case because reference search parameters such as Observation?subject= can refer to multiple target types (in this case: Patient, Group, Device, Location, and several more) and the server will have to do more work if it needs to check for all of these possible target types. http://localhost:8000/Observation?subject:Patient.identifier=http://ids|0001

Results: The search above will return the following resource: Observation/O1.

If Smile CDR Performance Tracing is enabled and you are performing chained searches without specifying the chain type and the reference would benefit from adding one, a warning will be added to the performance tracing events in the configured target.

5.3.5Reverse Chained References

 

In addition to searching for resources where a reference target has a given parameter value (i.e. chaining), you can also perform searches where a resource referring to the resource being searched for has a given target.

This is an advanced FHIR feature, and can be tricky to understand (and is generally tricky even for FHIR experts to remember the syntax!).

This syntax takes the form:

[resourceType]?_has:[referring resourceType]:[referring parameter]:[parameter]=[value]

An example may help to make this syntax more clear. Suppose you want to search for Patients named Simpson, but only include patients who are members of the group with identifier http://ids|8000. The "named Simpson" part is easy: you can perform a normal search for Patient?name=Simpson. However, the group part is harder. The following example shows how to do this. http://localhost:8000/Patient?name=Simpson&_has:Group:member:identifier=http://ids|8000

Note the _has parameter. It includes the following segments:

  • _has:Group – Include only Patients where a Group resource has a reference to the Patient.
  • :member – The Group must refer to the Patient at the path specified by the member search parameter on the Group resource. Note that member is not an element name in the resource, it is a search parameter name. These are often the same thing, but not always.
  • :identifier=http://ids|8000 – Only include Patients referred to by Group resources where the Group resource satisfies the search: Group?identifier=http://ids|8000.

Results: The search above will return the following resource: Patient/P1.

5.3.6Including Reference Targets

 

It is often convenient to be able to search for a collection of resources matching some given criteria, but to also include related resources in the same search result in order to avoid having to perform multiple lookups. This can be achieved using a search feature called includes.

Includes can be used to return any resources which are referred to by the resources returned by the initial search. This syntax takes the following forms:

[resourceType]?[any search parameters]&_include=* [resourceType]?[any search parameters]&_include=[resourceType]:[referring parameter]

The following example shows a search for any body-weight Observations, and includes the subject (Patient) associated with the returned Observations as well: http://localhost:8000/Observation?code=http://loinc.org|29463-7&_include=Observation:subject

Results: The search above will return the following resources: Observation/O1, Observation/O2, Patient/P1, and Patient/P2.

5.3.6.1Recursive Includes

In addition to returning resources that are returned by search results, you can also instruct the _include parameter to return resources referred to by resources that were added to the search results by the _include parameter. This is done using a modifier called :iterate. (Note that in older versions of the FHIR specification, this modifier was called :recurse. Many servers will support both modifiers and treat them identically.)

The following example shows a search for any body-weight Observations, and includes the subject (Patient) associated with the returned Observations, as well as the Organizations referred to by the subject: http://localhost:8000/Observation?code=http://loinc.org|29463-7&_include=Observation:subject&_include:iterate=Patient:organization

Results: The search above will return the following resource: Observation/O1, Observation/O2, Patient/P1, Patient/P2, and Organization/O1. If the :iterate modifier had not been included on the second _include parameter, the Organization would not have been included in the results.

5.3.7Reverse Includes

 

Resources can also be included based on references flowing in the other direction, meaning resources referring to the search results. This is referred to as reverse includes, or revincludes.

This syntax takes the following forms:

[resourceType]?[any search parameters]&_revinclude=* [resourceType]?[any search parameters]&_revinclude=[referring resourceType]:[referring parameter]

For example, the following search returns any patients with an identifier system of http://ids, and also returns any Group or Encounter resources which refer to these patients. Note also the token syntax of "[system]|" which means tokens with the given system and any value: http://localhost:8000/Patient?identifier=http://ids|&_revinclude=Group:member&_revinclude=Encounter:subject

Results: The search above will return the following resources: Patient/P1, Patient/P2, Group/G1, Encounter/E1, and Encounter/E2.

5.3.8Chaining into Contained Resources

 
To use this feature, you must enable this configuration property on your FHIR storage module. See Index Contained Resources to learn more about this feature.

While references between resources are almost always relative or absolute URLs to other separate resources, FHIR also provides a mechanism called containing where you can embed a resource inside another resource.

This feature is intended for situations where you do not have enough information to create a discrete identity for the resource in question. For example, suppose you have a collection of Observations you wish to model in FHIR, and you have the name and birthdate for the subject but no other information about them. In this case, you have no way of knowing whether two observations belonging to "John Smith" refer to the same person or not. This is an appropriate time to use contained resources.

Contained resources are placed within an array element called "contained" at the root of the resource, and are referred to elsewhere using the syntax { "reference": "#[id]" }. The following example shows an Observation with a contained Patient.

{ "resourceType": "Observation", "id": "O1", "contained": [
Contained Patient resource within Observation resource { "resourceType": "Patient", "id": "pat", "name": [ { "family": "Smith", "given": [ "John" ] } ], "birthDate": "1980-07-22" }
], "subject": {
Fragment reference to contained resource "reference": "#pat"
}, "status": "final", "code": { "coding": [ { "system": "http://loinc.org", "code": "29463-7", "display": "Body Weight" } ] }, "valueQuantity": { "value": 67.1, "unit": "kg", "system": "http://unitsofmeasure.org", "code": "kg" } }

Chaining can be used to search values in contained resources. The following URL can be used to fetch the resource above: http://localhost:8000/Observation?subject.name=Smith

5.3.9Canonical References

 

Some resource types define references to other resources which are canonical references. This means that the reference isn't a local or remote address to the resource in question, but instead is an absolute URL representing the canonical URL defined in the target resource. The canonical URL is a URL placed in an element called url at the root of the resource.

For example, Questionnaire resources define a canonical URL as shown in the example below.

{
	"resourceType": "Questionnaire",
	"id": "123",
	"meta": {
		"versionId": "2"
	},
	"url": "http://acme.org/foo-system/patient-survey",
	"version": "13.27Q",
	// ....additional fields not shown....
}

5.3.9.1Canonical Versions

Along with the canonical URL in the example url element shown above, a canonical version is also present in the version element. Note how these are both separate from the resource instance ID (123) and the resource instance version (2).

The canonical version is a business version as opposed to the technical version stored in the versionId element. The technical version (versionId) simply refers to the number of times that an individual resource instance has been updated on the server, with the latest version being considered the active one.

The canonical version on the other hand does not necessarily indicate which version is the newest, or which versioh is active. In reality, often times several business versions will be active and present on a server at the same time.

Where technical versions are always a number in HAPI FHIR / Smile CDR (these are alwyas assigned by the server), the business version is simply a string token in any format since it is defined externally to the server.

5.3.9.2References to Canonical Versions

A QuestionnaireResponse instance contains a reference to the Questionnaire using this canonical reference. For example this could look like the following:

{
	"resourceType": "QuestionnaireResponse",
	"id": "456",
	"questionnaire": "http://acme.org/foo-system/patient-survey",
	// ....additional fields not shown....
}

The QuestionnaireResponse could also contain a versioned canonical reference, which appends a pipe (|) and the version into the reference to indicate the specific business version being linked to.

{
	"resourceType": "QuestionnaireResponse",
	"id": "456",
	"questionnaire": "http://acme.org/foo-system/patient-survey|13.27Q",
	// ....additional fields not shown....
}

5.3.9.3Including/Reverse-Including Canonical References

Using the examples above, the following queries could be used to fetch both the QuestionnaireResponse and the corresponding Questionnaire shown in the examples.

Searching for the QuestionnaireResponse and including the Questionnaire it references: http://localhost:8000/QuestionnaireResponse?_id=456&_include=QuestionnaireResponse:questionnaire

Searching for the Questionnaire and reverse including the QuestionnaireResponse which references it: http://localhost:8000/Questionnaire?_id=123&_revinclude=QuestionnaireResponse:questionnaire

In HAPI FHIR / Smile CDR, note the following limitations to how includes/revincludes work for canonical references:

Include Style Example Notes
Include Reference _include=QuestionnaireResponse:questionnaire If the reference contains a versioned canonical reference, all resources which match the canonical URL will be returned, not just the resource with the matching canonical version.
Include All _include=* This style can be inefficient for the server to process when using canonical references! If your use case is performance sensitive, it is recommended to use the specific reference parameter as shown above. If the reference contains a versioned canonical reference, all resources which match the canonical URL will be returned, not just the resource with the matching canonical version.
Reverse Include Reference _revinclude=QuestionnaireResponse:questionnaire If the reference contains a versioned canonical reference, all resources which match the canonical URL will be returned, not just the resource with the matching canonical version.
Include All _revinclude=* This is not currently supported for canonical references, and will yield no results.

5.3.10Example: Using subject Group Membership to Filter Results

 

This example combines chaining and reverse chaining to create a very complicated query that achieves a very interesting result.

Suppose you want to search for Body-Weight observations, but only return observations where the subject is in a collection of patients.

If your collection of patients is small, a simple OR expression on a subject search parameter can do the trick as shown below: http://localhost:8000/Observation?code=http://loinc.org|29463-7&subject=Patient/P1,Patient/P2

Results: The search above will return the following resource: Observation/O1, Observation/O2.

However, what if your collection of patients is too large to be maintainable in a URL? Or what if you want to dynamically manage this collection of patients and reuse it across queries? In that case, you could create a Group resource and manage your list of patients there.

Then, you can perform the desired search using the Observation subject search parameter, but chaining on the patient using a reverse chain towards the Group resource. The following example shows this: http://localhost:8000/Observation?code=http://loinc.org|29463-7&subject:Patient._has:Group:member:_id=Group/G1

Note the subject parameter. It includes the following segments:

  • subject:Patient – Include only Observations where the subject is a Patient resource.
  • ._has:Group – The Patient must have a Group resource referring to it.
  • :member – The Group must refer to the Patient using the member search parameter.
  • :_id=Group/G1 – Only include Patients referred to by Group resources where the Group resource satisfies the search: _id=Group/G1. In other words, only the Group with ID Group/G1.

Results: The search above will return the following resources: Observation/O1, and Observation/O2.