_include & _revinclude
Include associated resources
A client can add related resources to a search result using (rev)include and with parameters. In ORM frameworks, such feature is sometimes called an "associations eager loading". This technique can save extra roundtrips from the client to the server and potential N+1 problem.
For example, you may want to get encounters with patients (each encounter refers to):
GET
PUT Patient
PUT Encounter
1
GET /Encounter?_include=Encounter:subject:Patient
Copied!
1
GET /Encounter?_with=subject{Patient}
Copied!
1
PUT /Patient
2
​
3
resourceType: Patient
4
id: pat-234
5
name:
6
- family: Smith
Copied!
1
PUT /Encounter
2
​
3
resourceType: Encounter
4
id: enc-234
5
subject:
6
resourceType: Patient
7
id: pat-234
8
class: {code: 'IMP',
9
system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode',
10
display: 'inpatient encounter'}
11
status: finished
Copied!
Or patients with conditions (i.e. by a reverse reference):
1
GET /Patient?_revinclude=Encounter:subject:Patient
Copied!
1
GET /Patient?_with=Encounter.subject
Copied!

_include

Syntax for include:
1
_include(:reverse|:iterate|:logical)=(source-type:)search-param:(:target-type)
Copied!
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. If you skip the source-type, it will be set to the resource-type you are searching for:
1
GET /Encounter?_include=subject:Patient
2
=> GET /Encounter?_include=Encounter:subject:Patient
Copied!
target-type is optional for not chained includes and means all referenced resource-types:
1
GET /Encounter?_include=subject
2
=> GET /Encounter?_include=subject:*
Copied!
For more explicit interpretation and for performance reason, client must provide target-type for chained includes!

_revinclude

Syntax for revinclude:
1
_revinclude(:reverse|:iterate|:logical)=(source-type:)search-param(:target-type)
Copied!
Interpretation: include all source-type resources, which refer target-type resources by search-param in the result set.

: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
PUT Patient
PUT Encounter
1
GET /Encounter?_include:logical=patient
Copied!
1
GET /Encounter?_with=patient:logical
Copied!
1
GET /Patient?_revinclude:logical=Encounter:patient:Patient
Copied!
1
GET /Patient?_with=Encounter.patient:logical
Copied!
1
PUT /Patient
2
​
3
resourceType: Patient
4
id: pat-123
5
identifier:
6
- {system: 'ssn', value: '78787878'}
Copied!
1
PUT /Encounter
2
​
3
resourceType: Encounter
4
id: enc-123
5
subject:
6
type: Patient
7
identifier: {system: 'ssn', value: '78787878'}
8
class: {code: 'IMP',
9
system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode',
10
display: 'inpatient encounter'}
11
status: finished
Copied!

_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. Please avoid using it!
_include=* could not be used as part of chained (rev)includes!
1
GET /Encounter?_include=*
Copied!

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 this modifier is optional (it's better to skip it).
GET
PUT RequestGroup
1
GET /RequestGroup?_include=encounter\
2
&_include=patient:Patient\
3
&_include=Patient:organization\
4
&_revinclude=AllergyIntolerance:patient:Patient\
5
&_revinclude=Condition:subject:Patient\
6
&_include=author:PractitionerRole\
7
&_include=PractitionerRole:practitioner:Pracitioner\
8
&_include=PractitionerRole:location\
9
&_revinclude=Contract:subject:PractitionerRole\
10
&_include=MedicationRequest:medication\
11
&_include=MedicationRequest:requester:PractitionerRole\
12
&_include=MedicationRequest:intended-performer:Organization\
13
&_include=MedicationRequest:intended-performer:Organization
Copied!
1
PUT /RequestGroup/example
2
​
3
encounter: {id: enc-234, resourceType: Encounter}
4
reasonCode:
5
- {text: Treatment}
6
authoredOn: '2019-03-06T17:31:00Z'
7
resourceType: RequestGroup
8
note:
9
- {text: Additional notes about the request group}
10
author: {display: Practitioner/1}
11
contained:
12
- id: medicationrequest-1
13
intent: proposal
14
status: unknown
15
subject: {id: pat-234, resourceType: Patient}
16
medication:
17
CodeableConcept: {text: Medication 1}
18
resourceType: MedicationRequest
19
- id: medicationrequest-2
20
intent: proposal
21
status: unknown
22
subject: {id: pat-234, resourceType: Patient}
23
medication:
24
CodeableConcept: {text: Medication 2}
25
resourceType: MedicationRequest
26
priority: routine
27
status: draft
28
id: example
29
groupIdentifier: {value: '00001', system: 'http://example.org/treatment-group'}
30
identifier:
31
- {value: requestgroup-1}
32
intent: plan
33
action:
34
- description: Administer medications at the appropriate time
35
textEquivalent: Administer medication 1, followed an hour later by medication 2
36
participant:
37
- {display: Practitioner/1}
38
title: Administer Medications
39
prefix: '1'
40
selectionBehavior: all
41
requiredBehavior: must
42
timing: {dateTime: '2019-03-06T19:00:00Z'}
43
groupingBehavior: logical-group
44
action:
45
- id: medication-action-1
46
type:
47
coding:
48
- {code: create}
49
resource: {localRef: medicationrequest-1}
50
description: Administer medication 1
51
- id: medication-action-2
52
type:
53
coding:
54
- {code: create}
55
resource: {localRef: medicationrequest-2}
56
description: Administer medication 2
57
relatedAction:
58
- offset:
59
Duration: {unit: h, value: 1}
60
actionId: medication-action-1
61
relationship: after-end
62
precheckBehavior: 'yes'
63
cardinalityBehavior: single
64
subject: {id: pat-234, resourceType: Patient}
65
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}
Copied!
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!
To save some keystrokes, you can group _(rev)include params of the same level as a comma separated list:
1
GET /RequestGroup?_include=encounter,patient:Patient,author:PractitionerRole
Copied!
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
PUT Obs1
PUT Obs2
PUT Obs3
1
GET /Observation?_include:recurse=has-member
Copied!
1
put /Observation/bloodgroup
2
​
3
category:
4
- text: Laboratory
5
coding:
6
- {code: laboratory,
7
system: 'http://terminology.hl7.org/CodeSystem/observation-category',
8
display: Laboratory}
9
value:
10
CodeableConcept:
11
text: A
12
coding:
13
- {code: '112144000', system: 'http://snomed.info/sct',
14
display: Blood group A (finding)}
15
resourceType: Observation
16
status: final
17
effective: {dateTime: '2018-03-11T16:07:54+00:00'}
18
id: bloodgroup
19
code:
20
text: Blood Group
21
coding:
22
- {code: 883-9, system: 'http://loinc.org',
23
display: 'ABO group [Type] in Blood'}
24
subject: {id: pat-234, resourceType: Patient}
Copied!
1
put /Observation/rhstatus
2
​
3
category:
4
- text: Laboratory
5
coding:
6
- {code: laboratory, system: 'http://terminology.hl7.org/CodeSystem/observation-category', display: Laboratory}
7
meta: {lastUpdated: '2019-12-17T13:44:27.218564Z', createdAt: '2019-12-17T13:44:27.218564Z', versionId: '99'}
8
value:
9
CodeableConcept:
10
text: A
11
coding:
12
- {code: '112144000', system: 'http://snomed.info/sct', display: Blood group A (finding)}
13
resourceType: Observation
14
status: final
15
effective: {dateTime: '2018-03-11T16:07:54+00:00'}
16
id: rhstatus
17
code:
18
text: Blood Group
19
coding:
20
- {code: 883-9, system: 'http://loinc.org', display: 'ABO group [Type] in Blood'}
21
subject: {id: pat-234, resourceType: Patient}
Copied!
1
put /Observation/bgpanel
2
​
3
category:
4
- text: Laboratory
5
coding:
6
- {code: laboratory, system: 'http://terminology.hl7.org/CodeSystem/observation-category', display: Laboratory}
7
hasMember:
8
- {id: bloodgroup, resourceType: Observation}
9
- {id: rhstatus, resourceType: Observation}
10
meta: {lastUpdated: '2019-12-17T13:45:37.780512Z', createdAt: '2019-12-17T13:45:37.780512Z', versionId: '106'}
11
resourceType: Observation
12
status: final
13
effective: {dateTime: '2018-03-11T16:07:54+00:00'}
14
id: bgpanel
15
code:
16
text: Blood Group Panel
17
coding:
18
- {code: 34532-2, system: 'http://loinc.org', display: ' Blood type and Indirect antibody screen panel - Blood'}
19
subject: {id: pat-234, resourceType: Patient}
Copied!
1
GET /Observation?_include:iterate=Observation:has-member:Observation
Copied!
GET
PUT Org1
PUT Org2
PUT Org3
PUT Org4
1
# get all children
2
GET /Organization?_revinclude:recurse=Organization:partof
Copied!
1
put /Organization/org-123
2
​
3
name: Blackwood Hospital
Copied!
1
put /Organization/org-234
2
​
3
name: Blackwood Hospital Department
4
partOf:
5
resourceType: Organization
6
id: org-123
Copied!
1
put /Organization/org-345
2
​
3
name: Blackwood Hospital Department Facility
4
partOf:
5
resourceType: Organization
6
id: org-234
Copied!
1
put /Organization/org-456
2
​
3
name: Blackwood Hospital Department Facility Room 1
4
partOf:
5
resourceType: Organization
6
id: org-345
Copied!
1
# get all children
2
GET /Organization?_revinclude:iterate=Organization:partof:Organization
Copied!
1
# get all parents
2
GET /Organization?_include:recurse=partof
Copied!
1
# get all parents
2
GET /Organization?_include:iterate=Organization:partof:Organization
Copied!

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.
1
expr = param-expr (space param-expr)*
2
param-expr = param ( '{' typed-ref-expr (space typed-ref-expr)* '}')?
3
typed-ref-expr = resource-type | resource-type '{' expr '}'
4
param = resource-type '.' param-name (':recur' | ':logical') ? | param-name (':recur' | ':logical') ?
5
space = ',' | ' ' | '\n'
6
param-name = ALPAHNUM
Copied!
Examples:
1
Encounter?_with=patient
2
=> Encounter?_include=Encounter:patient
3
---
4
Encounter?_with=patient,participant
5
=> Encounter?_include=Encounter:patient,Encounter:participant
6
---
7
Encounter?_with=patient{Patient}
8
=> Encounter?_include=Encounter:patient:Patient
9
---
10
Encounter?_with=patient{Patient{organization}}
11
=> Encounter?_include=Encounter:patient:Patient&
12
_include(:iterate)=Patient:organization
13
---
14
Encounter?_with=patient{Patient{organization{Organization{partof:recur}}}}
15
=> Encounter?_include=Encounter:patient:Patient&
16
_include(:iterate)=Patient:organization
17
_include(:recurse)=Organization:parto-of
18
---
19
Patient?_with=organization,Condition.patient,MedicationStatement.patient{medication}
20
=> Patient?_include=Patient:organization&
21
_revinclude=Condition:patient:Patient
22
_revinclude=MedicationStatement:patient:Patient
23
_include=MedicationStatement:medication
24
---
25
RequestGroup?_with=
26
author
27
patient{Patient{organization,AllergyIntolerance.patient}}
28
target{
29
MedicationRequest{
30
medication
31
intended-performer{Organization}
32
requester{PractitionerRole{practitioner,location}}}}
33
=>
34
RequestGroup?_include=patient,author
35
&_include:iterate=RequestGroup:target:MedicationRequest
36
&_include:iterate=MedicationRequest:medication
37
&_include:iterate=MedicationRequest:requester:PractitionerRole
38
&_include:iterate=MedicationRequest:intended-performer:Organization
39
&_include:iterate=PractitionerRole:practitioner
40
&_include:iterate=Patient:organization
41
&_include:iterate=PractitionerRole:location
42
&_revinclude:iterate=AllergyIntolerance:patient
43
---
44
Organization?partof:recur{Organization}
45
=> Organization?_include:recurse=partof:Organization
Copied!

(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:
1
GET /Encounter?_include=patient&_elements=id,status,Patient.name,Patient.birthDate
Copied!
​
Last modified 5mo ago