FHIR:Vissue-MM-2759 Search result examples: verschil tussen versies

Uit informatiestandaarden
Naar navigatie springen Naar zoeken springen
 
(53 tussenliggende versies door 2 gebruikers niet weergegeven)
Regel 1: Regel 1:
 
{{IssuePaginaWaarschuwing|MM-2759|FHIR:V1.0_Search_result_examples}}
 
{{IssuePaginaWaarschuwing|MM-2759|FHIR:V1.0_Search_result_examples}}
 
__NOINDEX__
 
__NOINDEX__
 +
__NUMBEREDHEADINGS__
 +
=Search result examples=
 +
This page provides guidance on how a server could return search results. Examples are provided in XML format but could have been in JSON format as well. Please note: these examples are not considered to be part of the normative content of the implementation guide.
  
=Example: read support for all resources=
+
=Examples=
The server offers read support for all resources that it has; each resource has a stable {{fhir|Resource.id}} and is accessible through a stable RESTful URL.
+
==Server supports the read operation for all resources==
 
+
{| class="wikitable" style="width: 100%;"
<syntaxhighlight lang="xml" highlight="" style="max-height:400px; overflow: auto;">
+
|-
 +
| '''Scenario'''
 +
| The server offers read support for all resources that it has, meaning that each resource has a stable {{fhir|Resource.id}} and is accessible through a stable RESTful URL.
 +
|-
 +
| '''Request'''
 +
| <pre> GET [base]/Observation?code=http://loinc.org|85354-9</pre>
 +
|-
 +
| '''Response'''
 +
|
 +
* Searchset Bundle containing 1 Observation resource.
 +
* References from the Observation resource are to other resources on the server.
 +
|-
 +
| '''Response content'''
 +
(click to expand)
 +
|
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-read_operations_xml"><span class="mw-customtoggle-read_operations_xml">▶ Response - XML</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="xml" highlight="">
 
<Bundle xmlns="http://hl7.org/fhir" >
 
<Bundle xmlns="http://hl7.org/fhir" >
     <!-- Bundle.id is not different than any other Resource.id -->
+
     ...
    <id value="example-id1"/>
 
  
 
     <!-- Bundle.type should be set to 'searchset' -->
 
     <!-- Bundle.type should be set to 'searchset' -->
Regel 37: Regel 56:
 
                     <reference value="Patient/patient-123" />
 
                     <reference value="Patient/patient-123" />
 
                 </subject>
 
                 </subject>
 +
                ...
 
             </Observation>
 
             </Observation>
 
         </resource>
 
         </resource>
Regel 46: Regel 66:
 
</Bundle>
 
</Bundle>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</div></div>
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-read_operations_json"><span class="mw-customtoggle-read_operations_json">▶ Response - JSON</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="json" highlight="">
 +
{
 +
  "resourceType": "Bundle",
 +
  ...
 +
 
 +
  //Bundle.type should be set to 'searchset'
 +
  "type": "searchset",
 +
 
 +
  // Bundle.total is set to the number of matches for the request
 +
  "total": 1,
 +
 
 +
  // The 'self link' shows the search request as how it was understood by the server
 +
  "link": [
 +
    {
 +
      "relation": "self",
 +
      "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
 +
    }
 +
  ],
 +
 
 +
  "entry": [
 +
    {
 +
    // The Observation resource is accessible through a RESTful URL, which is used for the fullUrl
 +
      "fullUrl": "https://example-server.nl/fhir/Observation/observation-123",
 +
     
 +
      "resource": {
 +
        "resourceType": "Observation",
 +
     
 +
        // The Resource.id MUST be populated when it is accessible using a RESTful URL.
 +
        "id": "observation-123",
 +
        ...
 +
        // The Patient resource resides on the same server and can be referenced using a relative URL.
 +
        // An absolute URL could be used in this case as well.     
 +
        "subject": {
 +
          "reference": "Patient/patient-123"
 +
        }
 +
      },
 +
      "search": {
 +
        // Resources that match the search request have mode set to 'match'
 +
        "mode": "match"
 +
      }
 +
    }
 +
  ]
 +
}
 +
</syntaxhighlight>
 +
</div></div>
 +
|}
  
=Example 2: server only supports search=
+
==Server doesn't support read operations==
The server supports doesn't support the read operation, for example because it's a FHIR facade that is unable to link a stable id to a certain entry in the underlying database. For this reason, it only supports searching for data.
+
{| class="wikitable" style="width: 100%;"
 
+
|-
<syntaxhighlight lang="xml" highlight="" style="max-height:400px; overflow: auto;">
+
| '''Scenario'''
 +
| The server supports doesn't support the read operation, for example because it's a FHIR facade that is unable to link a stable id to a certain entry in the underlying database. For this reason, it only supports searching for data.
 +
|-
 +
| '''Request'''
 +
| <pre> GET [base]/Observation?code=http://loinc.org|85354-9</pre>
 +
|-
 +
| '''Response'''
 +
|
 +
* Searchset Bundle containing 1 Observation resource and all referenced resources.
 +
* References from the Observation resource are to other resources within the Bundle.
 +
* All resources in the Bundle are identified using a temporary {{fhir|fullUrl}}.
 +
|-
 +
| '''Response content'''
 +
(click to expand)
 +
|
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-no_read_operations_xml"><span class="mw-customtoggle-no_read_operations_xml">▶ Response - XML</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="xml" highlight="">
 
<Bundle xmlns="http://hl7.org/fhir">
 
<Bundle xmlns="http://hl7.org/fhir">
     <!-- Bundle.id is not different than any other Resource.id -->
+
     ...
    <id value="example-id2"/>
 
  
 
     <!-- Bundle.type should be set to 'searchset' -->
 
     <!-- Bundle.type should be set to 'searchset' -->
Regel 79: Regel 164:
 
         <resource>
 
         <resource>
 
             <Patient>
 
             <Patient>
                 ....
+
                 <!--
 +
                  When returning a resource, Resource.id SHOULD be populated. When no stable .id is available, the temporary UUID, without the urn:uuid part, MAY be used instead.
 +
                  However, it is recommended in this case to simply leave out the Resource.id
 +
                <id value="69aefd96-b37d-4323-866b-762536c03375"/>
 +
                -->
 +
                ...
 
             </Patient>
 
             </Patient>
 
         </resource>
 
         </resource>
Regel 90: Regel 180:
 
     <entry>
 
     <entry>
 
         <!--  
 
         <!--  
           Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle. (?)
+
           Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
 
           Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
 
           Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
 
           for this resource as well.
 
           for this resource as well.
Regel 106: Regel 196:
 
         </resource>
 
         </resource>
 
         <search>
 
         <search>
             <mode value="match"/> <!-- Resources that match the search request have mode set to 'match' -->
+
             <!-- Resources that match the search request have mode set to 'match' -->
 +
            <mode value="match"/>
 
         </search>
 
         </search>
 
     </entry>
 
     </entry>
 
</Bundle>
 
</Bundle>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</div></div>
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-no_read_operations_json"><span class="mw-customtoggle-no_read_operations_json">▶ Response - JSON</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="json" highlight="">
 +
{
 +
    "resourceType": "Bundle",
 +
    ...
 +
 +
    // Bundle.type should be set to 'searchset'
 +
    "type": "searchset",
 +
 +
    // Bundle.total is still set to the number of _matches_, even though more resources are included in the Bundle.
 +
    "total": "1",
 +
 +
    // The "self link" reflects the search as it was understood by the server
 +
    "link": [
 +
    {
 +
        "relation": "self",
 +
        "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
 +
    }
 +
    ],
 +
    // The server is unable to offer a stable RESTful URL to the Patient resource, but it needs to satisfy the requirement
 +
    // that all resources are resolvable. Therefore, it includes the referenced Patient resource in the searchset Bundle.
 +
    "entry": [
 +
        {
 +
            // Since the server is unable to produce a RESTful URL for reading the resource, so it uses an ephemeral fullUrl so that other
 +
            //  resources in the Bundle can refer to it.
 +
            "fullUrl": "urn:uuid:69aefd96-b37d-4323-866b-762536c03375",
 +
            "resource": {
 +
                "resourceType": "Patient",
 +
                // When returning a resource, Resource.id SHOULD be populated. When no stable .id is available,
 +
                // the temporary UUID, without the urn:uuid part, MAY be used instead.
 +
                // However, it is recommended in this case to simply leave out the Resource.id
 +
                // "id": "69aefd96-b37d-4323-866b-762536c03375",
 +
                ...
 +
            },
 +
            "search": {
 +
                // When resources are additionally included in the searchset Bundle while there's no direct match, .search.mode should be set to 'include'.
 +
                "mode": "include"
 +
            }
 +
        },
 +
        {
 +
            // Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
 +
            // Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
 +
            // for this resource as well.
 +
            "fullUrl": "urn:uuid:799c5790-f2aa-4045-8c19-a0d54773a059",
 +
            "resource": {
 +
                "resourceType": "Observation",
 +
                ...
 +
                "subject": {
 +
                    // The server doesn't support read for the Patient resource, so it's included in the Bundle using an ephemeral fullUrl.
 +
                    "reference": "urn:uuid:69aefd96-b37d-4323-866b-762536c03375"
 +
                },
 +
                ...
 +
            }
 +
          }
 +
        ],
 +
            "search": {
 +
            // Resources that match the search request have mode set to 'match'
 +
            "mode": "match"
 +
        }
 +
    ]
 +
}
 +
</syntaxhighlight>
 +
</div></div>
 +
|}
  
=Example 3: read support for some resources (hypothetical)=
+
==Server supports read for some resources (hypothetical)==
<syntaxhighlight lang="xml" highlight="" style="max-height:400px; overflow: auto;">
+
{| class="wikitable" style="width: 100%;"
 +
|-
 +
| '''Scenario'''
 +
| The server is able to produce a stable RESTful URL for the Patient resource, but not for the Observation resource. This is a highly hypothetical situation to demonstrate the boundaries of the reference resolving mechanism in FHIR Bundles.
 +
|-
 +
| '''Request'''
 +
| <pre> GET [base]/Observation?code=http://loinc.org|85354-9</pre>
 +
|-
 +
| '''Response'''
 +
|
 +
* Searchset Bundle containing 1 Observation resource.
 +
* References from the Observation resource are to other resources on the server, using an absolute URL.
 +
* The Observation resource is identified using a temporary {{fhir|fullUrl}}.
 +
|-
 +
| '''Response content'''
 +
(click to expand)
 +
|
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-hypothetical_xml"><span class="mw-customtoggle-hypothetical_xml">▶ Response - XML</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="xml" highlight="">
 
<Bundle xmlns="http://hl7.org/fhir" >
 
<Bundle xmlns="http://hl7.org/fhir" >
     <id value="example-id3"/> <!-- Bundle.id is not different than any other Resource.id -->
+
     ...
     <type value="searchset"/> <!-- Bundle.type should be set to 'searchset' -->
+
   
     <total value="1"/> <!-- Bundle.total is still set to the number of _matches_, even though more resources are included -->
+
     <!-- Bundle.type should be set to 'searchset' -->
 +
     <type value="searchset"/>
 +
 
 +
    <!-- Bundle.total is still set to the number of _matches_, even though more resources are included -->
 +
    <total value="1"/>
 +
   
 +
    <!-- The "self link" shows the search request as how it was understood by the server -->
 
     <link>
 
     <link>
 
         <relation value="self"/>
 
         <relation value="self"/>
         <url value="https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"/> <!-- The "self link" reflects the search as it was understood by the server -->
+
         <url value="https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"/>
 
     </link>
 
     </link>
 +
   
 +
    <entry>
 +
        <!--
 +
          Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
 +
          for this resource.
 +
          Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
 +
        -->
 +
        <fullUrl value="urn:uuid:e07ffa10-c043-4dd6-aa52-6ac273c82da9"/>
 +
        <resource>
 +
            <Observation>
 +
                ...
 +
                <subject>
 +
                    <!--
 +
                      The server supports read for the Patient resource, so an absolute URL can be used.
 +
                      Note that a relative URL is invalid in this case, because it is deemed relative to the fullUrl of the Observation resource.
 +
                      Since this fullUrl is not a RESTful URL, a relative URL cannot be resolved to an actual URL. -->
 +
                    -->
 +
                    <reference value="http://example-server.nl/Patient/patient-123" />
 +
                </subject>
 +
                ...
 +
            </Observation>
 +
        </resource>
 +
        ...
 +
    </entry>
 +
</Bundle>
 +
</syntaxhighlight>
 +
</div></div>
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-hypothetical_json"><span class="mw-customtoggle-hypothetical_json">▶ Response - JSON</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="json" highlight="">
 +
{
 +
    "resourceType": "Bundle",
 +
    ...
 +
   
 +
    // Bundle.type should be set to 'searchset'
 +
    "type": "searchset",
 +
 +
    // Bundle.total is still set to the number of _matches_, even though more resources are included
 +
    "total": "1",
 +
   
 +
    // The 'self link' shows the search request as how it was understood by the server
 +
    "link": {
 +
        "relation": "self",
 +
        "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
 +
    }
 +
   
 +
    "entry": [
 +
        {
 +
            // Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
 +
            // for this resource.
 +
            // Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
 +
            "fullUrl": "urn:uuid:e07ffa10-c043-4dd6-aa52-6ac273c82da9",
 +
            "resource": {
 +
                "resourceType": "Observation",
 +
                ...
 +
                "subject": {
 +
                    // The server supports read for the Patient resource, so an absolute URL can be used.
 +
                    // Note that a relative URL is invalid in this case, because it is deemed relative to the fullUrl of the Observation resource.
 +
                    // Since this fullUrl is not a RESTful URL, a relative URL cannot be resolved to an actual URL.
 +
                    "reference": "http://example-server.nl/Patient/patient-123"
 +
                },
 +
                ...
 +
            },
 +
            ...
 +
        }
 +
    ]
 +
}
 +
</syntaxhighlight>
 +
</div></div>
 +
|}
 +
 +
==Invalid: server doesn't support read operations and uses contained resources instead==
 +
{| class="wikitable" style="background-color: #f3d2d2; width: 100%;"
 +
|-
 +
| colspan="2" | {{warning|This example demonstrates how this SHOULD NOT be handled}}
 +
|-
 +
| '''Scenario'''
 +
| The server supports doesn't support the read operation, for example because it's a FHIR facade that is unable to link a stable id to a certain entry in the underlying database. For this reason, it only supports searching for data.
 +
|-
 +
| '''Request'''
 +
| <pre> GET [base]/Observation?code=http://loinc.org|85354-9</pre>
 +
|-
 +
| '''Response'''
 +
|
 +
* Searchset Bundle containing 1 Observation resource.
 +
* The referenced Patient resource is contained within the Observation resource.
 +
 +
This approach is invalid! Resources should only be contained if they cannot have an independent existence outside of the resource containing it. This is not the case in the current situation.
 +
|-
 +
| '''Response content'''
 +
(click to expand)
 +
|
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-contained_xml"><span class="mw-customtoggle-contained_xml">▶ Response - XML</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="xml">
 +
<Bundle xmlns="http://hl7.org/fhir" >
 +
    ...
 
     <entry>
 
     <entry>
         <fullUrl value="urn:uuid:799c5790-f2aa-4045-8c19-a0d54773a059"/> <!-- The server doesn't support read, so the fullUrl is an ephemeral identifier that only has value within the Bundle -->
+
         <fullUrl value="urn:uuid:2290607c-79e8-47ed-a23e-b8c3d5f224b2"/>
 
         <resource>
 
         <resource>
 
             <Observation>
 
             <Observation>
                 <!-- <id value="799c5790-f2aa-4045-8c19-a0d54773a059" /> it is recommended NOT to use the ephemeral id as Resource.id, but the opinions on this topic are divided -->
+
                 ...
 +
                <contained>
 +
                    <Patient>
 +
                        <id value="patient1"/>
 +
                        ...
 +
                    </Patient>
 +
                </contained>
 
                 ...
 
                 ...
 
                 <subject>
 
                 <subject>
                     <reference value="http://example-server.nl/Patient/patient-123" /> <!-- The server supports read for the Patient resource, so an absolute URL could be used -->
+
                     <!--
                    <!-- <reference value="Patient/patient-123" /> However, a relative URL is invalid because it is relative to the fullUrl of the Observation resource.
+
                      Wrong approach: the server is unable to offer a stable RESTful URL to the Patient resource, but it needs to
                                                                  Since this fullUrl is not a RESTful URL, the relative URL cannot be resolved to an actual URL. -->
+
                      satisfy the requirement that all resources are resolvable. Therefore, it sends the Patient resource as a contained
 +
                      resource within the Observation resource.
 +
                      Resources should only be contained if they cannot have an independent existence outside of the resource
 +
                      containing it. This is not the case in the current situation, so this approach is invalid!
 +
                    -->
 +
                    <reference value="#patient1" />  
 
                 </subject>
 
                 </subject>
 +
                ...
 
             </Observation>
 
             </Observation>
 
         </resource>
 
         </resource>
         <search>
+
         ...
            <mode value="match"/> <!-- Resources that match the search request have mode set to 'match' -->
 
        </search>
 
 
     </entry>
 
     </entry>
 
</Bundle>
 
</Bundle>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
</div></div>
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-contained_json"><span class="mw-customtoggle-contained_json">▶ Response - JSON</span>
 +
<div class="mw-collapsible-content">
 +
<syntaxhighlight lang="json">
 +
{
 +
    "resourceType": "Bundle",
 +
    ...
 +
    "entry": [
 +
        {
 +
            "fullUrl": "urn:uuid:2290607c-79e8-47ed-a23e-b8c3d5f224b2",
 +
            "resource": {
 +
                "resourceType": "Observation",
 +
                ...
 +
                "contained": [
 +
                    {
 +
                        "resourceType": "Patient",
 +
                        "id": "patient1",
 +
                        ...
 +
                    }
 +
                ],
 +
                ...
 +
                "subject": {
 +
                    // Wrong approach: the server is unable to offer a stable RESTful URL to the Patient resource, but it needs to
 +
                    // satisfy the requirement that all resources are resolvable. Therefore, it sends the Patient resource as a contained
 +
                    // resource within the Observation resource.
 +
                    // Resources should only be contained if they cannot have an independent existence outside of the resource
 +
                    // containing it. This is not the case in the current situation, so this approach is invalid!
 +
                    "reference": "#patient1"
 +
                },
 +
                ...
 +
            }
 +
        },
 +
        ...
 +
    ]
 +
}
 +
</syntaxhighlight>
 +
</div></div>
 +
|}

Huidige versie van 24 jun 2022 om 08:54


1 Search result examples

This page provides guidance on how a server could return search results. Examples are provided in XML format but could have been in JSON format as well. Please note: these examples are not considered to be part of the normative content of the implementation guide.

2 Examples

2.1 Server supports the read operation for all resources

Scenario The server offers read support for all resources that it has, meaning that each resource has a stable Resource.id and is accessible through a stable RESTful URL.
Request
 GET [base]/Observation?code=http://loinc.org|85354-9
Response
  • Searchset Bundle containing 1 Observation resource.
  • References from the Observation resource are to other resources on the server.
Response content

(click to expand)

▶ Response - XML
<Bundle xmlns="http://hl7.org/fhir" >
    ...

    <!-- Bundle.type should be set to 'searchset' -->
    <type value="searchset"/>

    <!-- Bundle.total is set to the number of matches for the request -->
    <total value="1"/>
    
    <!-- The "self link" shows the search request as how it was understood by the server -->
    <link>
        <relation value="self"/>
        <url value="https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"/>
    </link>

    <entry>
        <!-- The Observation resource is accessible through a RESTful URL, which is used for the fullUrl -->
        <fullUrl value="https://example-server.nl/fhir/Observation/observation-123"/>

        <resource>
            <Observation>

                <!-- The Resource.id MUST be populated when it is accessible using a RESTful URL. -->
                <id value="observation-123" />
                ...
                <subject>
                    <!-- The Patient resource resides on the same server and can be referenced using a relative URL.
                         An absolute URL could be used in this case as well. -->
                    <reference value="Patient/patient-123" />
                </subject>
                ...
            </Observation>
        </resource>
        <search>
            <!-- Resources that match the search request have mode set to 'match' -->
            <mode value="match"/>
        </search>
    </entry>
</Bundle>
▶ Response - JSON
{
  "resourceType": "Bundle",
   ...
   
  //Bundle.type should be set to 'searchset'
  "type": "searchset", 
  
  // Bundle.total is set to the number of matches for the request
  "total": 1,
  
  // The 'self link' shows the search request as how it was understood by the server
  "link": [
    {
      "relation": "self",
      "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
    }
  ],
  
  "entry": [
    {
    // The Observation resource is accessible through a RESTful URL, which is used for the fullUrl
      "fullUrl": "https://example-server.nl/fhir/Observation/observation-123",
      
      "resource": {
        "resourceType": "Observation",
      
        // The Resource.id MUST be populated when it is accessible using a RESTful URL.
        "id": "observation-123",
        ...
        // The Patient resource resides on the same server and can be referenced using a relative URL.
        // An absolute URL could be used in this case as well.       
        "subject": {
          "reference": "Patient/patient-123"
        }
      },
      "search": {
        // Resources that match the search request have mode set to 'match'
        "mode": "match"
      }
    }
  ]
}

2.2 Server doesn't support read operations

Scenario The server supports doesn't support the read operation, for example because it's a FHIR facade that is unable to link a stable id to a certain entry in the underlying database. For this reason, it only supports searching for data.
Request
 GET [base]/Observation?code=http://loinc.org|85354-9
Response
  • Searchset Bundle containing 1 Observation resource and all referenced resources.
  • References from the Observation resource are to other resources within the Bundle.
  • All resources in the Bundle are identified using a temporary fullUrl.
Response content

(click to expand)

▶ Response - XML
<Bundle xmlns="http://hl7.org/fhir">
    ...

    <!-- Bundle.type should be set to 'searchset' -->
    <type value="searchset"/>

    <!-- Bundle.total is still set to the number of _matches_, even though more resources are included in the Bundle. -->
    <total value="1"/>

    <!-- The "self link" reflects the search as it was understood by the server -->
    <link>
        <relation value="self"/>
        <url value="https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"/>
    </link>

    <!--
      The server is unable to offer a stable RESTful URL to the Patient resource, but it needs to satisfy the requirement
      that all resources are resolvable. Therefore, it includes the referenced Patient resource in the searchset Bundle.
    -->
    <entry>
        <!-- 
          Since the server is unable to produce a RESTful URL for reading the resource, so it uses an ephemeral fullUrl so that other 
          resources in the Bundle can refer to it.
        -->
        <fullUrl value="urn:uuid:69aefd96-b37d-4323-866b-762536c03375">
        <resource>
            <Patient>
                <!-- 
                  When returning a resource, Resource.id SHOULD be populated. When no stable .id is available, the temporary UUID, without the urn:uuid part, MAY be used instead.
                  However, it is recommended in this case to simply leave out the Resource.id
                <id value="69aefd96-b37d-4323-866b-762536c03375"/>
                -->
                ...
            </Patient>
        </resource>
        <search>
            <!-- When resources are additionally included in the searchset Bundle while there's no direct match, .search.mode should be set to 'include'. -->
            <mode value="include" />
        </search>
    </entry>

    <entry>
        <!-- 
          Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
          Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
          for this resource as well.
        -->
        <fullUrl value="urn:uuid:799c5790-f2aa-4045-8c19-a0d54773a059"/>
        <resource>
            <Observation>
                ...
                <subject>
                    <!-- The server doesn't support read for the Patient resource, so it's included in the Bundle using an ephemeral fullUrl. -->
                    <reference value="urn:uuid:69aefd96-b37d-4323-866b-762536c03375" /> 
                </subject>
                ...
            </Observation>
        </resource>
        <search>
            <!-- Resources that match the search request have mode set to 'match' -->
            <mode value="match"/>
        </search>
    </entry>
</Bundle>
▶ Response - JSON
{
    "resourceType": "Bundle",
    ...

    // Bundle.type should be set to 'searchset'
    "type": "searchset",

    // Bundle.total is still set to the number of _matches_, even though more resources are included in the Bundle.
    "total": "1",

    // The "self link" reflects the search as it was understood by the server
    "link": [
     {
        "relation": "self",
        "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
     }
    ],
    // The server is unable to offer a stable RESTful URL to the Patient resource, but it needs to satisfy the requirement
    // that all resources are resolvable. Therefore, it includes the referenced Patient resource in the searchset Bundle.
    "entry": [
        {
            // Since the server is unable to produce a RESTful URL for reading the resource, so it uses an ephemeral fullUrl so that other 
            //  resources in the Bundle can refer to it.
            "fullUrl": "urn:uuid:69aefd96-b37d-4323-866b-762536c03375",
            "resource": {
                "resourceType": "Patient",
                // When returning a resource, Resource.id SHOULD be populated. When no stable .id is available,
                // the temporary UUID, without the urn:uuid part, MAY be used instead.
                // However, it is recommended in this case to simply leave out the Resource.id
                // "id": "69aefd96-b37d-4323-866b-762536c03375",
                ...
            },
            "search": {
                // When resources are additionally included in the searchset Bundle while there's no direct match, .search.mode should be set to 'include'.
                "mode": "include"
            }
        },
        {
            // Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
            // Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
            // for this resource as well.
            "fullUrl": "urn:uuid:799c5790-f2aa-4045-8c19-a0d54773a059",
            "resource": {
                "resourceType": "Observation",
                ...
                "subject": {
                    // The server doesn't support read for the Patient resource, so it's included in the Bundle using an ephemeral fullUrl.
                    "reference": "urn:uuid:69aefd96-b37d-4323-866b-762536c03375"
                },
                ...
            }
          }
        ],
            "search": {
            // Resources that match the search request have mode set to 'match'
            "mode": "match"
        }
    ]
}

2.3 Server supports read for some resources (hypothetical)

Scenario The server is able to produce a stable RESTful URL for the Patient resource, but not for the Observation resource. This is a highly hypothetical situation to demonstrate the boundaries of the reference resolving mechanism in FHIR Bundles.
Request
 GET [base]/Observation?code=http://loinc.org|85354-9
Response
  • Searchset Bundle containing 1 Observation resource.
  • References from the Observation resource are to other resources on the server, using an absolute URL.
  • The Observation resource is identified using a temporary fullUrl.
Response content

(click to expand)

▶ Response - XML
<Bundle xmlns="http://hl7.org/fhir" >
    ...
    
    <!-- Bundle.type should be set to 'searchset' -->
    <type value="searchset"/>

    <!-- Bundle.total is still set to the number of _matches_, even though more resources are included -->
    <total value="1"/>
    
    <!-- The "self link" shows the search request as how it was understood by the server -->
    <link>
        <relation value="self"/>
        <url value="https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"/>
    </link>
    
    <entry>
        <!-- 
          Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
          for this resource.
          Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
        -->
        <fullUrl value="urn:uuid:e07ffa10-c043-4dd6-aa52-6ac273c82da9"/>
        <resource>
            <Observation>
                ...
                <subject>
                    <!--
                      The server supports read for the Patient resource, so an absolute URL can be used.
                      Note that a relative URL is invalid in this case, because it is deemed relative to the fullUrl of the Observation resource.
                      Since this fullUrl is not a RESTful URL, a relative URL cannot be resolved to an actual URL. -->
                    -->
                    <reference value="http://example-server.nl/Patient/patient-123" /> 
                </subject>
                ...
            </Observation>
        </resource>
        ...
    </entry>
</Bundle>
▶ Response - JSON
{
    "resourceType": "Bundle",
    ...
    
    // Bundle.type should be set to 'searchset'
    "type": "searchset",

    // Bundle.total is still set to the number of _matches_, even though more resources are included
    "total": "1",
    
    // The 'self link' shows the search request as how it was understood by the server
    "link": {
        "relation": "self",
        "url": "https://example-server.nl/fhir/Observation?code=http://loinc.org|85354-9"
    }
    
    "entry": [
        {
            // Since the server is unable to produce a RESTful URL for reading the Observation resource, it creates an ephemeral fullUrl
            // for this resource.
            // Note that the fullUrl MUST be populated, even if this resource is not referred by any other resource within the Bundle.
            "fullUrl": "urn:uuid:e07ffa10-c043-4dd6-aa52-6ac273c82da9",
            "resource": {
                "resourceType": "Observation",
                ...
                "subject": {
                    // The server supports read for the Patient resource, so an absolute URL can be used.
                    // Note that a relative URL is invalid in this case, because it is deemed relative to the fullUrl of the Observation resource.
                    // Since this fullUrl is not a RESTful URL, a relative URL cannot be resolved to an actual URL.
                    "reference": "http://example-server.nl/Patient/patient-123"
                },
                ...
            },
            ...
        }
    ]
}

2.4 Invalid: server doesn't support read operations and uses contained resources instead

Scenario The server supports doesn't support the read operation, for example because it's a FHIR facade that is unable to link a stable id to a certain entry in the underlying database. For this reason, it only supports searching for data.
Request
 GET [base]/Observation?code=http://loinc.org|85354-9
Response
  • Searchset Bundle containing 1 Observation resource.
  • The referenced Patient resource is contained within the Observation resource.

This approach is invalid! Resources should only be contained if they cannot have an independent existence outside of the resource containing it. This is not the case in the current situation.

Response content

(click to expand)

▶ Response - XML
<Bundle xmlns="http://hl7.org/fhir" >
    ...
    <entry>
        <fullUrl value="urn:uuid:2290607c-79e8-47ed-a23e-b8c3d5f224b2"/>
        <resource>
            <Observation>
                ...
                <contained>
                    <Patient>
                        <id value="patient1"/>
                        ...
                    </Patient>
                </contained>
                ...
                <subject>
                    <!--
                      Wrong approach: the server is unable to offer a stable RESTful URL to the Patient resource, but it needs to
                      satisfy the requirement that all resources are resolvable. Therefore, it sends the Patient resource as a contained
                      resource within the Observation resource.
                      Resources should only be contained if they cannot have an independent existence outside of the resource
                      containing it. This is not the case in the current situation, so this approach is invalid!
                    -->
                    <reference value="#patient1" /> 
                </subject>
                ...
            </Observation>
        </resource>
        ...
    </entry>
</Bundle>
▶ Response - JSON
{
    "resourceType": "Bundle",
    ...
    "entry": [
        {
            "fullUrl": "urn:uuid:2290607c-79e8-47ed-a23e-b8c3d5f224b2",
            "resource": {
                "resourceType": "Observation",
                ...
                "contained": [
                    {
                        "resourceType": "Patient",
                        "id": "patient1",
                        ...
                    }
                ],
                ...
                "subject": {
                    // Wrong approach: the server is unable to offer a stable RESTful URL to the Patient resource, but it needs to
                    // satisfy the requirement that all resources are resolvable. Therefore, it sends the Patient resource as a contained
                    // resource within the Observation resource.
                    // Resources should only be contained if they cannot have an independent existence outside of the resource
                    // containing it. This is not the case in the current situation, so this approach is invalid!
                    "reference": "#patient1"
                },
                ...
            }
        },
        ...
    ]
}