Since 2402, Aidbox has a FHIR-compliant behavior for _include and _revinclude parameters. It is recommended to turn it on.
To toggle on:
BOX_SEARCH_INCLUDE_CONFORMANT=true
Also, there's a way to set the maximum number of iterations for :iterate modifier:
BOX_SEARCH_INCLUDE_ITERATE__MAX=5
Differences between FHIR-conformant and Aidbox mode
Due to historical reasons Aidbox treats the _include and _revinclude parameters slightly differently from the behavior described in the specification (without FHIR-conformant mode on).
The _(rev)include search parameter without the :iterate or :recurse modifier should only be applied to the initial ("matched") result. However, in Aidbox mode, it is also applied to the previous _(rev)include.
The _(rev)include parameter with the :iterate(:recurse) modifier should be repeatedly applied to the result with included resources. However, in Aidbox mode, it only resolves cyclic references.
In Aidbox mode, it is possible to search without specifying source type: GET /Patient?_include=general-practitioner, but in the FHIR-conformant mode it is not possible.
Here search-param is a name of the search parameter with the type reference defined for source-type.
This query can be interpreted in the following manner. For the source-type resources in the result include all target-type resources, which are referenced by the search-param.
target-type is optional for not chained includes and means all referenced resource-types:
GET /Encounter?_include=Encounter:subject=> GET /Encounter?_include=Encounter:subject:*
For more explicit interpretation and for performance reason, client must provide target-type for chained includes!
_include=*
You can include all resources referenced from the search result using *. This is considered bad practice because it's too implicit.
This feature is only implemented for conformance with the FHIR specification.
Interpretation: include all source-type resources, which refer target-type resources by search-param in the result set.
Chained (rev)includes
Client can chain (rev)includes to load next level of references. (Rev)includes should go in a proper loading order. According to the FHIR specification, for chained includes a client must specify the :iterate modifier. However, in Aidbox mode this modifier is optional.
GET /RequestGroup?_include=encounter\&_include=patient:Patient\&_include=Patient:organization\&_revinclude=AllergyIntolerance:patient:Patient\&_revinclude=Condition:subject:Patient\&_include=author:PractitionerRole\&_include=PractitionerRole:practitioner:Pracitioner\&_include=PractitionerRole:location\&_revinclude=Contract:subject:PractitionerRole\&_include=MedicationRequest:medication\&_include=MedicationRequest:requester:PractitionerRole\&_include=MedicationRequest:intended-performer:Organization\&_include=MedicationRequest:intended-performer:Organization
PUT /RequestGroup/example
encounter: {id: enc-234, resourceType: Encounter}
reasonCode:
- {text: Treatment}
authoredOn: '2019-03-06T17:31:00Z'
resourceType: RequestGroup
note:
- {text: Additional notes about the request group}
author: {display: Practitioner/1}
contained:
- id: medicationrequest-1
intent: proposal
status: unknown
subject: {id: pat-234, resourceType: Patient}
medication:
CodeableConcept: {text: Medication 1}
resourceType: MedicationRequest
- id: medicationrequest-2
intent: proposal
status: unknown
subject: {id: pat-234, resourceType: Patient}
medication:
CodeableConcept: {text: Medication 2}
resourceType: MedicationRequest
priority: routine
status: draft
id: example
groupIdentifier: {value: '00001', system: 'http://example.org/treatment-group'}
identifier:
- {value: requestgroup-1}
intent: plan
action:
- description: Administer medications at the appropriate time
textEquivalent: Administer medication 1, followed an hour later by medication 2
participant:
- {display: Practitioner/1}
title: Administer Medications
prefix: '1'
selectionBehavior: all
requiredBehavior: must
timing: {dateTime: '2019-03-06T19:00:00Z'}
groupingBehavior: logical-group
action:
- id: medication-action-1
type:
coding:
- {code: create}
resource: {localRef: medicationrequest-1}
description: Administer medication 1
- id: medication-action-2
type:
coding:
- {code: create}
resource: {localRef: medicationrequest-2}
description: Administer medication 2
relatedAction:
- offset:
Duration: {unit: h, value: 1}
actionId: medication-action-1
relationship: after-end
precheckBehavior: 'yes'
cardinalityBehavior: single
subject: {id: pat-234, resourceType: Patient}
text: {div: '<div xmlns="http://www.w3.org/1999/xhtml">Example RequestGroup illustrating related actions to administer medications in sequence with time delay.</div>', status: generated}
Client must always specify target-type and source-type for intermediate (rev)includes because this is explicit and allows Aidbox to prepare dependency graph before query!
Here is the discussion in the FHIR chat about the :iterate ambiguity. We appreciate your opinion!
Recursive (rev)includes
For self-referencing resources, you can specify the :recurse or :iterate modifier with source-type=target-type to recursively get all children or parents:
GET /Observation?_include:recurse=Observation:has-member
PUT /Observation/bloodgroup
category:
- text: Laboratory
coding:
- {code: laboratory,
system: 'http://terminology.hl7.org/CodeSystem/observation-category',
display: Laboratory}
value:
CodeableConcept:
text: A
coding:
- {code: '112144000', system: 'http://snomed.info/sct',
display: Blood group A (finding)}
resourceType: Observation
status: final
effective: {dateTime: '2018-03-11T16:07:54+00:00'}
id: bloodgroup
code:
text: Blood Group
coding:
- {code: 883-9, system: 'http://loinc.org',
display: 'ABO group [Type] in Blood'}
subject: {id: pat-234, resourceType: Patient}
PUT /Observation/rhstatus
category:
- text: Laboratory
coding:
- {code: laboratory, system: 'http://terminology.hl7.org/CodeSystem/observation-category', display: Laboratory}
meta: {lastUpdated: '2019-12-17T13:44:27.218564Z', createdAt: '2019-12-17T13:44:27.218564Z', versionId: '99'}
value:
CodeableConcept:
text: A
coding:
- {code: '112144000', system: 'http://snomed.info/sct', display: Blood group A (finding)}
resourceType: Observation
status: final
effective: {dateTime: '2018-03-11T16:07:54+00:00'}
id: rhstatus
code:
text: Blood Group
coding:
- {code: 883-9, system: 'http://loinc.org', display: 'ABO group [Type] in Blood'}
subject: {id: pat-234, resourceType: Patient}
GET /Observation?_include:iterate=Observation:has-member:Observation
# get all childrenGET /Organization?_revinclude:recurse=Organization:partof
put /Organization/org-123
name: Blackwood Hospital
put /Organization/org-234
name: Blackwood Hospital Department
partOf:
resourceType: Organization
id: org-123
put /Organization/org-345
name: Blackwood Hospital Department Facility
partOf:
resourceType: Organization
id: org-234
put /Organization/org-456
name: Blackwood Hospital Department Facility Room 1
partOf:
resourceType: Organization
id: org-345
(rev)include and _elements
You can use the extended elements parameter to control elements of (rev)included resources by prefixing desired elements with the resource type:
GET /Encounter?_include=patient&_elements=id,status,Patient.name,Patient.birthDate
:logical modifier
If you provide :logical modifier, Aidbox will include logically referenced resources as well. Logical reference means reference with attribute type set to resource-type and identifier attribute set to one of identifier of referenced resource.
Example:
GET /Encounter?_include:logical=Encounter:patient
GET /Encounter?_with=patient:logical
GET /Patient?_revinclude:logical=Encounter:patient:Patient
GET /Patient?_with=Encounter.patient:logical
PUT /PatientresourceType:Patientid:pat-123identifier:- {system:'ssn',value:'78787878'}
PUT /EncounterresourceType:Encounterid:enc-123subject:type:Patientidentifier: {system:'ssn',value:'78787878'}class: {code:'IMP',system:'http://terminology.hl7.org/CodeSystem/v3-ActCode',display:'inpatient encounter'}status:finished
Using the _with parameter
FHIR (rev)include syntax is non-DRY and sometimes confusing. We introduced the _with parameter that is a simple (like GraphQL) DSL to describe includes in a more compact way.