├── .gitignore
├── CRUD operations
├── img
│ ├── curl.png
│ ├── pic1.png
│ ├── pic10.png
│ ├── pic11.png
│ ├── pic12.png
│ ├── pic13.png
│ ├── pic2.png
│ ├── pic3.png
│ ├── pic4.png
│ ├── pic5.png
│ ├── pic6.png
│ ├── pic7.png
│ ├── pic8.png
│ ├── pic9.png
│ ├── post-clients.png
│ └── postman-example.png
└── lesson.md
├── FHIRPath
└── lesson.md
├── Profiling
├── images
│ ├── Conformance_resources_relationship.png
│ └── Profiling_context.png
├── lesson.md
└── profile_examples
│ ├── ObservationProfile.json
│ ├── PatientProfile.json
│ └── PractitionerProfile.json
├── README.md
├── SearchParameter
├── images
│ ├── DefaultSearchParameterPatient.png
│ ├── SearchParameterDeclaration.png
│ └── SearchParameterResource.png
└── lesson.md
├── Search_References_ChainHasIncludeRevinclude
├── images
│ └── graph.png
└── lesson.md
├── Terminology
└── CodeSystem_and_ValueSet
│ ├── img
│ └── ValueSet.svg
│ └── lesson.md
├── Transactions
├── img
│ ├── bundle-types.png
│ ├── fhir-bundle.png
│ └── paging.png
└── lesson.md
└── examples
└── Search_References_ChainHasIncludeRevinclude
├── FHIR_Tutorial_Series_FHIR_Search_References_Flow.svg
├── test-data-1.json
└── test-data-2.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # IDEs and editors
4 | /.idea
5 | .project
6 | .classpath
7 | .c9/
8 | *.launch
9 | .settings/
10 | *.sublime-workspace
11 |
12 | # IDE - VSCode
13 | .vscode/*
14 | !.vscode/settings.json
15 | !.vscode/tasks.json
16 | !.vscode/launch.json
17 | !.vscode/extensions.json
18 |
19 | # System Files
20 | .DS_Store
21 | Thumbs.db
22 | .vscode/settings.json
23 |
--------------------------------------------------------------------------------
/CRUD operations/img/curl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/curl.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic1.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic10.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic11.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic12.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic13.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic2.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic3.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic4.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic5.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic6.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic7.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic8.png
--------------------------------------------------------------------------------
/CRUD operations/img/pic9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/pic9.png
--------------------------------------------------------------------------------
/CRUD operations/img/post-clients.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/post-clients.png
--------------------------------------------------------------------------------
/CRUD operations/img/postman-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/CRUD operations/img/postman-example.png
--------------------------------------------------------------------------------
/CRUD operations/lesson.md:
--------------------------------------------------------------------------------
1 | # FHIR CRUD operations
2 |
3 |
4 | ## FHIR CRUD references:
5 |
6 | - Introduction
7 | - HTTP post clients
8 | - Getting first resource from the FHIR server
9 | - Updating resource in the FHIR server
10 | - Adding a new resource to the FHIR server
11 | - Deleting the resource in the FHIR server
12 | - Group Discussion and Q&A
13 |
14 |
15 | ## Introduction
16 |
17 | In this tutorial, we will walk through the basic CRUD operations.
18 |
19 | CRUD stands for Create, Read, Update & Delete. These are the four main actions that you will use to interact with the FHIR resources within a FHIR server.
20 |
21 | REST stands for 'Representational state transfer' and RESTFul just means a system that conforms to the constraints of REST.
22 |
23 | Understanding these four operations is essential to working with any RESTful service which a FHIR server is an implementation of.
24 |
25 |
26 | ## Step 1: Http post clients
27 |
28 | The simplest way to retrieve and send FHIR resources to and from a FHIR server is to use a Http post client.
29 | The most popular clients are Postman and Insomnia. Each of them has pros and cons.
30 |
31 | 
32 |
33 | What is a post client? It is a tool that allows you to talk to servers using Hypertext Transfer Protocol (HTTP).
34 | When you use an internet browser the browser is converting your clicks and text into HTTP to send to the web server and the server returns content,
35 | your web page, back via HTTP. The browser then interprets the content as a web page and displays it on screen. When we work with FHIR the content is not a web page but rather XML or JSON.
36 | Our web browser is not very good at displaying raw XML or JSON so we need a HTTP client so that we can talk in HTTP and view the XML or JSON returned.
37 |
38 | If you don’t want to use any post clients, you can use curl.
39 | Curl is a tool which can be used to execute HTTP requests from the command line, and is commonly installed on Linux/OSX systems.
40 | Terminal command: man curl
41 |
42 | 
43 |
44 | Example of GET request with curl: curl -v GET https://try.smilecdr.com:8000/Patient/37078
45 |
46 | - -v [options] provide more details
47 |
48 | The good example of using the Postman application
49 |
50 | 
51 |
52 | ## Step 2: Getting your first resource from the FHIR server
53 |
54 | ### FHIR Read / vRead
55 | If you know the ID of a resource on a FHIR server, you can read back the most recent version of that resource by performing a read operation.
56 | The read uses an HTTP GET against the URL [baseUrl]/[resourceType]/[id].
57 |
58 | 
59 |
60 | You can also include a version string in the URL in order to request a specific version of the resource by performing a vread operation.
61 | The vread uses an HTTP GET against the URL [baseUrl]/[resourceType]/[id]/_history/[versionId].
62 | You can execute this request with cURL using the following command:
63 |
64 | 
65 |
66 | ## Step 3: Updating your resource in the FHIR server
67 |
68 | ### FHIR update
69 | You can update an existing resource on a FHIR server by performing an update operation. The update uses an HTTP PUT against the URL [baseUrl]/[resourceType]/[id].
70 | This PUT should have (at a minimum) a Content-Type header that specifies the MIME type of the payload.
71 | We used the Accept property to tell the server the format (XML or JSON) we wanted to be returned by the server.
72 |
73 | 
74 |
75 | The following example shows a simple update using a JSON payload. In this example, we are taking the previously created resource from above and updating it.
76 | We will change the birth date and add an address. Note the ID 37078 in the URL, resource body and headers. When you are trying this yourself,
77 | make sure to use the ID that was returned from the server in the steps above.
78 |
79 | 
80 |
81 | Curl example:
82 |
83 | 
84 |
85 | ### FHIR Patch
86 | You can patch a resource on a FHIR server by performing a patch operation. The patch uses an HTTP PATCH agaisnt the URL [baseUrl]/[resourceType]/[id].
87 | This operation requries a Content-Type header that specifies the MIME type of the payload. For a JSON patch payload the header value would be: application/json-patch+json.
88 | For a XML patch payload the header value would be: application/xml-patch+xml. The body of the PATCH payload must be in a specific format for JSON and XML requests.
89 |
90 | 
91 |
92 | ## Step 4: Adding a new resource to the FHIR server
93 |
94 | ### FHIR Create
95 | A client may create a new resource on a FHIR server by performing a Create operation. The create uses an HTTP POST against the URL [baseUrl]/[resourceType].
96 | This POST should have (at a minimum) a Content-Type header which specifies the mimetype of the payload. The following example shows a simple create using a JSON Payload.
97 |
98 | 
99 |
100 | Curl example:
101 |
102 | 
103 |
104 | ## Step 5: Deleting a resource from the FHIR server
105 |
106 | ### FHIR Delete
107 | You can delete a resource on a FHIR server by performing a delete operation. The delete uses an HTTP DELETE against the URL [baseUrl]/[resourceType]/[id].
108 | This operation performs a logical delete, which has a specific set of semantics: The resource is marked as deleted, and it will no longer appear in search results.
109 | The version number of the resource is incremented (essentially, a new deleted version is created). Previous versions of the resource are not physically deleted.
110 | The resource may be un-deleted by updating it again. The following example shows a simple delete of the resource created and updated in the examples above.
111 | Curl example: curl -v -X DELETE https://try.smilecdr.com:8000/Patient/37078
112 |
113 | 
114 |
115 | ### Cascading Delete
116 | With cascading deletes enabled, a user can perform the delete on Patient/A and all of the child resources will be deleted as well.
117 | In order to perform a cascading delete, three things must occur: Cascading Deletes Enabled setting must be enabled on the FHIR Storage module.
118 | Then, the user performing the operation must have the FHIR_DELETE_CASCADE_ALLOWED permission, as well as a specific permission allowing the child resource to be deleted.
119 | For example, you might grant the user the FHIR_DELETE_CASCADE_ALLOWED and FHIR_ALL_DELETE permissions.
120 | Finally, to perform a cascaded delete, the client HTTP request must include either a special URL parameter (_cascade) or a special header to indicate that a cascading delete is desired.
121 |
122 | Example: DELETE /Patient/123?_cascade=delete
123 |
124 | ### Transactional Delete
125 | The FHIR Transaction operation can be used to delete multiple resources at the same time.
126 | This is useful if you have chains or collections of resources to delete at ones, but also can be used to delete circular references.
127 | To delete multiple resources in a transaction, POST a Bundle such as the following to the root of your FHIR endpoint.
128 |
129 | 
130 |
131 | ### Expunge operation ($expunge)
132 | In some cases we need to completely delete data from the server.
133 | The $expunge operation is a powerful operation that can physically delete old versions of resources, deleted resources, or even all data in the database.
134 |
135 | 
136 |
137 | ### Instance level expunge
138 | The $expunge operation can be invoked against a single resource instance, or even an individual version of a resource instance. If invoked at the instance level
139 |
140 | 
141 |
142 | ### Type level expunge
143 | The $expunge operation can be invoked at the type level. In this mode, all resources of a given type will be processed with the same rules as at the instance level.
144 |
145 | 
146 |
147 | ## Group discussions and QA:
148 |
149 | 1. What does idempotent means in REST api?
150 | 1. What are the basic methods used for CRUD operations?
151 | 1. Which method is used to update the resource?
152 | 1. PUT and PATCH method difference?
153 | 1. PUT and POST method difference?
154 | 1. How to update Organisation resource, any example request?
155 | 1. Write the URL to delete the patient resource.
156 | 1. Mention which markup language can be used in restful api?
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/FHIRPath/lesson.md:
--------------------------------------------------------------------------------
1 | # FHIRPath: JsonPath/XPath for Fhir!
2 |
3 | ## What is it
4 | FHIRPath is a standard by which a formal representation of logic can be applied to FHIR Resources in a reproducible manner. It is used for both resource navigation and extraction of data from resources. FHIRPath allows you to programmatically retrieve only portions of data you care about, or portions that fulfill some given criteria. All official implementations are listed [here](https://wiki.hl7.org/index.php?title=FHIRPath_Implementations), and if you want a playground to play around in, you can check out [this online tool](https://hl7.github.io/fhirpath.js/). If you are familiar with JSONPath or XMLPath, you are already halfway towards understanding the abilities and purpose of FHIRPath.
5 |
6 | ## Resource Navigation
7 |
8 | FHIRPath can be used for navigating through resources. Consider the following Patient
9 | ```json
10 | {
11 | "resourceType": "Patient",
12 | "id": "1553",
13 | "name": [
14 | {
15 | "family": "Smith",
16 | "given": [
17 | "John",
18 | "Scott"
19 | ]
20 | }
21 | ],
22 | "telecom": [
23 | {
24 | "use": "home",
25 | "system": "email"
26 | },
27 | {
28 | "use": "work",
29 | "value": "(1) 226 791 5555",
30 | "system": "phone"
31 | }
32 | }
33 | ```
34 | To use FHIRPath to list the Patient's given names, the query would look like this:
35 | ```bash
36 | > Patient.name.given
37 | {"John", "Scott"}
38 | ```
39 | The FHIRPath evaluator will return the requested query as a collection of elements. Note that it is always a collection that is returned, even if it is only a single element:
40 | ```bash
41 | > Patient.name.family
42 | {"Smith"}
43 | ```
44 | This may seem like an odd thing to do; The reason for this is in the documentation:
45 | ```
46 | Collection-centric: FHIRPath deals with all values as collections, allowing it to easily deal with information models with repeating elements.
47 | ```
48 | Since everything is a collection, you can safely call collection methods on the results of a FHIRPath query:
49 | ```bash
50 | > Patient.name.given.first()
51 | {"John"}
52 | ```
53 | Some examples of such methods are `first()`, `last()`,`tail()`,`skip()`, and `children()`. Documentation for these can be found in the [functions documentation](http://hl7.org/fhirpath/#functions).
54 | While everything in FHIRPath evaluation is a collection, it also does singleton collection evaluation. This allows you to perform the following expressions without having to select precisely which index of value you want:
55 | ```bash
56 | > Patient.name.family + " " + Patient.name.family
57 | {"Smith Smith"}
58 | ```
59 | `Warning`: This only works when the elements are actually singletons. In the following case, the FHIRPath evaluator will throw an error:
60 | ```bash
61 | > Patient.name.given + " " + Patient.name.family
62 | ERROR
63 | ```
64 | This happens since `Patient.name.first` is not a singleton collection, but contains two elements. To correct this, you need to specify which index of the collection you want to use.
65 | ```bash
66 | > Patient.name.given[0] + " " + Patient.name.family
67 | {"John Smith"}
68 | > Patient.name.given.last() + " " + Patient.name.family
69 | {"Scott Smith"}
70 | ```
71 |
72 | ## Polymorphism in navigation and selection
73 | Oftentimes collections of data in a FHIR resource are not all of the same type. For example, an `Observation` may have several type options for `value`. It could potentially be `Quantity`, or may be `boolean`, and a host of other options. Consider the following Query:
74 | ```
75 | > Observation.value.unit #This will return units for all value types.
76 | > Observation.value.ofType(Quantity).unit #This will return units only if the value is a Quantity
77 | ```
78 | `ofType()` will add only elements matching the type to the returned collection.
79 |
80 | ## Expressions
81 |
82 | When you query a FHIRPath evaluator, what you are passing it is called an `Expression`. FHIRPath expressions can consist of paths, literals, operators, and function invocations,
83 |
84 | * Paths are things like `Patient.name.given`, `Observation.value`
85 | * Literals are things like `'a'`, `true`, `0`, `@2020-02-04`
86 | * Operators are things like `/`, `>`, `|`
87 | * Function invocations are things like `.where()` , `.count()` , `.substring()`
88 |
89 | ```bash
90 | > Observation.value is Quantity
91 | true
92 | ```
93 |
94 | ### Filtering and projection of results in expressions
95 | There are cases where you may not want _all_ of a collection. For example, what if you want all of a Patient's Telecom nodes, but only the ones which have a value of `system=phone` (e.g. you only want their phone numbers:
96 | ```bash
97 | > Patient.telecom.where(system='phone').value
98 | {"(1) 226 791 5555"}
99 | ```
100 | the `.where()` function will be called on each element in the collection, and add it to the resulting collection if the criteria in the `.where()` evaluates to true.
101 |
102 | Similarly, if you have a collection of elements and want to select with criteria from it, you can use the projection function `select()` in order to select from the collection stream. For example, imagine for a moment that our patient from above had another name on top of their first name entry:
103 |
104 |
105 | ```bash
106 | > Bundle.entry.select(resource as Patient)
107 | # This returns a collection of patients that were entries in the bundle, and ignores all non-patient resources.
108 |
109 | > Bundle.entry.select((resource as Patient).telecom.where(system = 'phone'))
110 | # This returns a collection of telecoms where system=phone from each resource in the bundle that was a patient.
111 | ```
112 | Now let's imagine our patient from earlier had a second name on top of their first one, like so:
113 | ```json
114 | {
115 | "family": "Smith2",
116 | "given": [
117 | "Frank"
118 | ]
119 | }
120 | ```
121 |
122 | ### Crossing Resource Boundaries
123 | Occasionally there are contained resources held within a given resource. Normally, FHIRPath cannot resolve these automatically, so there is a function in the spec called `resolve()` which will allow you to resolve a contained resource. The actual implementation and functionality is up to the FHIRContext evaluating the request, so it is not strictly defined in the spec. However, here is a sample query showing the usage of resolve:
124 | ```bash
125 | CareTeam.member.resolve().ofType(Practitioner).name.given.first()
126 | ```
127 | This query returns a collection of all the first given names of all the Practitioners that are members of a CareTeam.
128 |
129 |
130 | Consider this query which will generate a collection of two strings, each representing a full name from a name element.
131 | ```bash
132 | > Patient.name.select(given.first() + ' ' + family)
133 | {"John Smith", "Frank Smihth2"}
134 |
135 | ```
136 |
137 | ### Aggregations
138 |
139 | You can write general purpose aggregations, which follow the same rules as other functions, but you also have access to the special $total variable while inside. The signature of such a method is `.aggregate(aggregator: expression [, init: value])`
140 | For example, this will generate a sum of all the data of all SampledData values in all observations in a bundle.
141 | ```bash
142 | Bundle.entry
143 | .select(resource as Observation).value
144 | .ofType(SampledData)
145 | .aggregate($this.data + $total, 0)
146 |
147 | ```
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/Profiling/images/Conformance_resources_relationship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Profiling/images/Conformance_resources_relationship.png
--------------------------------------------------------------------------------
/Profiling/images/Profiling_context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Profiling/images/Profiling_context.png
--------------------------------------------------------------------------------
/Profiling/lesson.md:
--------------------------------------------------------------------------------
1 | # [FHIR Profiling](https://www.hl7.org/fhir/profiling.html)
2 |
3 |
4 | ## Definition
5 |
6 | * Adapting the FHIR specifications to a particular context of use.
7 | * Variation in context across the world in the healthcare ecosystem
8 |
9 | 
10 |
11 | ## Conformance Module
12 |
13 | * Conformance resources represent the adaptations in a computable fashion
14 | * **Implementation Guide (IG)** :- describes how FHIR is adapted to support a certain use case.
15 | * **Capability Statement** :- Uses Conformance resource to document how a client or server has implemented FHIR
16 |
17 | ## Conformance Resource
18 |
19 | * **StructureDefinition Resource** :- Defines how resources, extensions and data types are used.
20 | * **MessageDefinition Resource** :- Describes messages that can be sent or received
21 | * **OperationDefinition Resource** :- Describes addition operations in addition to the base specifications
22 | * **SearchParameter Resource** :- Describes additional search capabilities in addition to the base definition
23 | * **CompartmentDefinition Resource** :- Describes a logical grouping for resources (used in access control or search)
24 |
25 |
26 | 
27 |
28 | ## StructureDefinition Resource
29 |
30 | * This resource is used to define FHIR data structures :-
31 | * Resource
32 | * Extension
33 | * DataTypes
34 | * Implementors can use this resource to make constraints on the base definition
35 |
36 | #### StructureDefinition Resource Properties
37 |
38 | * **url** :- Unique identifier for StructureDefinition
39 | * **name** :- Name of the StructureDefinition
40 | * **baseDefinition** :- base of the current StructureDefinition
41 | * **Snapshot** :- This is a fully calculated form of structure
42 | * **Differential** :- Only contains constraints made onto the base structure, anything not mentioned in statement is implied to have no changes from the base
43 |
44 | ## $snapshot operation
45 |
46 | * Generates a StructureDefinition instance with a `snapshot` based on the differential in a specified StructureDefinition.
47 | * In orde to generate a valid `snapshot`, `baseDefinition` of a StrcutureDefinition must have a valid snapshot.
48 | * Query Structure :-
49 | * POST :- [base]/StructureDefinition/$snapshot
50 | * GET, PUT :- [base]/StructureDefinition/[id]/$snapshot
51 |
52 | ## Slicing
53 |
54 | * Slicing is basically restrictions on each element of a resource property with `cardinality >= 1`.
55 | * **Discriminator** :- In order to differentiate between slices, each resource element which is slices will include a property known as the `discriminator` to tell them apart. The `discriminator` consists of two mandatory fields :-
56 | * Type :- Slice Type
57 | * Path :- FHIRPath expression
58 |
59 | #### Slice Types
60 |
61 | | Type | Use | Scenario |
62 | |---------|-------------------------------------------------|----------------------------------------------------------------------------------------------|
63 | | value | Static comparison | Usually used for comparing static codes |
64 | | exists | If the property exists & then another condition | Usually used for Backboneelements |
65 | | pattern | Comparing pattern | Usually used for CodeSystems like LOINC, SNOMED CT |
66 | | type | value[x]/pattern[x] | Usually used for resource properties which support more than one datatype or primitive types |
67 | | profile | Validate data type against profile | Used for validating datatype with a custom profile |
68 |
69 | #### Slicing Rules
70 |
71 | When an element of a fixed cardinality m..n is sliced, the following rules apply: -
72 | * Each slice cannot have a greater cardinality than the maximum number of slices allowed.
73 | * The sum of the maximum cardinalities can be larger than n.
74 | * The sum of the minimum cardinalities must be less or equal to n.
75 | * Each individual slice can have a minimum cardinality of 0 (less than m - the only situation where this is allowed), but the total number of elements in the instance must still be greater or equal to m.
76 |
77 |
78 | ## $validate Operation
79 |
80 | * The validate operation checks whether the attached content would be acceptable while performing CRUD operations.
81 | * Query structure :-
82 | * POST :- [base]/Resource/$validate
83 | * GET, PUT, DELETE :- [base]/Resource/[id]/$validate
84 |
85 | ## Extensions
86 |
87 | * Creating extensions inside a profile by using a StructureDefinition resource
88 | * Define context i.e. where can it be used, target structure: resource, datatype, extension
89 | * Example :- [US Core Patient Profile](https://www.hl7.org/fhir/us/core/StructureDefinition-us-core-patient.html)
90 |
--------------------------------------------------------------------------------
/Profiling/profile_examples/ObservationProfile.json:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "StructureDefinition",
3 | "url": "http://hapi.fhir.org/baseR4/StructureDefinition/DiabetesObservationProfile",
4 | "name": "DiabetesObservationProfile",
5 | "status": "active",
6 | "kind": "resource",
7 | "abstract": false,
8 | "derivation": "specialization",
9 | "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Observation",
10 | "type": "Observation",
11 | "differential": {
12 | "element": [
13 | {
14 | "min": 0,
15 | "max": "3",
16 | "id": "Observation.category",
17 | "path": "Observation.category",
18 | "definition": "A code that classifies the general type of observation being made.",
19 | "slicing": {
20 | "discriminator": [
21 | {
22 | "type": "pattern",
23 | "path": "coding"
24 | },
25 | {
26 | "type": "pattern",
27 | "path": "coding"
28 | }
29 | ],
30 | "rules": "open",
31 | "ordered": false
32 | }
33 | },
34 | {
35 | "min": 0,
36 | "max": "1",
37 | "id": "Observation.category:Systolic",
38 | "path": "Observation.category",
39 | "sliceName": "Systolic",
40 | "patternCodeableConcept": {
41 | "coding": [
42 | {
43 | "code": "8480-6",
44 | "display": "Systolic"
45 | }
46 | ]
47 | }
48 | },
49 | {
50 | "min": 0,
51 | "max": "1",
52 | "id": "Observation.category:Diastolic",
53 | "path": "Observation.category",
54 | "sliceName": "Diastolic",
55 | "patternCodeableConcept": {
56 | "coding": [
57 | {
58 | "code": "8462-4",
59 | "display": "Diastolic"
60 | }
61 | ]
62 | }
63 | }
64 | ]
65 | }
66 | }
--------------------------------------------------------------------------------
/Profiling/profile_examples/PatientProfile.json:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "StructureDefinition",
3 | "url": "http://hapi.fhir.org/baseR4/StructureDefinition/PatientProfile",
4 | "name": "PatientProfile",
5 | "status": "active",
6 | "kind": "resource",
7 | "abstract": false,
8 | "derivation": "specialization",
9 | "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Patient",
10 | "type": "Patient",
11 | "differential": {
12 | "element": [
13 | {
14 | "min": 0,
15 | "max": "2",
16 | "id": "Patient.extension",
17 | "path": "Patient.extension",
18 | "definition": "Optional Extension Element - found in all resources.",
19 | "slicing": {
20 | "discriminator": [
21 | {
22 | "type": "type",
23 | "path": "$this"
24 | }
25 | ],
26 | "rules": "open",
27 | "ordered": false
28 | }
29 | },
30 | {
31 | "min": 1,
32 | "max": "1",
33 | "id": "Patient.extension.value[x]:BirthPlaceSlice",
34 | "path": "Patient.extension.value[x]",
35 | "sliceName": "BirthPlaceSlice",
36 | "type": [
37 | {
38 | "code": "string"
39 | }
40 | ]
41 | }
42 | ]
43 | }
44 | }
--------------------------------------------------------------------------------
/Profiling/profile_examples/PractitionerProfile.json:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "StructureDefinition",
3 | "url": "http://hapi.fhir.org/baseR4/StructureDefinition/PractitionerProfile",
4 | "name": "PractitionerProfile",
5 | "status": "active",
6 | "kind": "resource",
7 | "abstract": false,
8 | "derivation": "specialization",
9 | "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Practitioner",
10 | "type": "Practitioner",
11 | "differential": {
12 | "element": [
13 | {
14 | "min": 1,
15 | "max": "3",
16 | "id": "Practitioner.telecom",
17 | "path": "Practitioner.telecom",
18 | "definition": "A contact detail for the practitioner, e.g. a telephone number or an email address.",
19 | "slicing": {
20 | "discriminator": [
21 | {
22 | "type": "value",
23 | "path": "use"
24 | }
25 | ],
26 | "rules": "open",
27 | "ordered": false
28 | }
29 | },
30 | {
31 | "min": 1,
32 | "max": "1",
33 | "id": "Practitioner.telecom:practitioner_home_phone",
34 | "path": "Practitioner.telecom",
35 | "sliceName": "practitioner_home_phone",
36 | "fixedContactPoint": {
37 | "use": "home"
38 | }
39 | }
40 | ]
41 | }
42 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FHIR Tutorial
2 |
3 | This is the home of the FHIR Tutorial, an open collaborative effort to develop a training package, led by the team at [Smile CDR](https://smilecdr.com).
4 |
5 | This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
6 |
7 | # Table of Contents
8 |
9 | Note: These are not being created in their final order, so they are not (yet) intended to be read sequentially.
10 |
11 | * [Search / References / Chain, *_has*, *_include*, *_revinclude*](Search_References_ChainHasIncludeRevinclude/lesson.md)
12 |
13 | * [FHIRPath](FHIRPath/lesson.md)
14 |
15 | * [Transactions](Transactions/lesson.md)
16 |
17 | * [REST CRUD operations - Create, Read, Update, Delete](CRUD%20operations/lesson.md)
18 |
19 | * [Search Parameter Types](SearchParameter/lesson.md)
20 |
21 | * [Profiling](Profiling/lesson.md)
22 |
23 | * [Terminology - CodeSystem & ValueSet](Terminology/CodeSystem_and_ValueSet/lesson.md)
24 |
--------------------------------------------------------------------------------
/SearchParameter/images/DefaultSearchParameterPatient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/SearchParameter/images/DefaultSearchParameterPatient.png
--------------------------------------------------------------------------------
/SearchParameter/images/SearchParameterDeclaration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/SearchParameter/images/SearchParameterDeclaration.png
--------------------------------------------------------------------------------
/SearchParameter/images/SearchParameterResource.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/SearchParameter/images/SearchParameterResource.png
--------------------------------------------------------------------------------
/SearchParameter/lesson.md:
--------------------------------------------------------------------------------
1 | # FHIR Search Parameters
2 |
3 | ## Definition
4 |
5 | - A search parameter defines a named search item that can be used to search/filter on a FHIR resource.
6 | - A SearchParameter resource is a FHIR resource that can be used to define/describe a search parameter supported by a given server.
7 |
8 |
9 | ## What does SearchParameter resource declare ?
10 |
11 | 
12 |
13 | ## Default SearchParameter for Patient.gender
14 |
15 | 
16 |
17 | Default Search Parameter Registry :- [http://hl7.org/fhir/searchparameter-registry.html](http://hl7.org/fhir/searchparameter-registry.html).
18 |
19 |
20 | ## SearchParameter Types
21 |
22 | | Type | Definition |
23 | |---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
24 | | Number | Whole number or decimal |
25 | | Date/DateTime | Date and time parameter formatted as:
yyyy-mm-ddThh:mm:ss[Z\|(+\|-)hh:mm]
|
26 | | String | Simple string. Case and accent insensitive. May contain spaces. |
27 | | URI | Uniform Resource Identifier. Example:
http://acme.org/fhir/ValueSet/123
urn:oid:1.2.3.4.5
|
28 | | Token | Used for values that are part of a code system or namespace. Includes:
Coding
CodeableConcept
Identifier
ContactPoint
code
Can include both a code system and code value or just a code value. Examples.
identifier= http://acme.org/patient\|2345
gender=male
code=http://acme.org/conditions/codes\|ha125
|
29 | | Quantity | Used for quantity values that include a numeric value and possibly a unit of measure code.The unit of measure code will include a code value and optionally a code system. Examples:
value-quantity=5.4\|http://unitsofmeasure.org\|mg
value-quantity=5.4\|\|mg
value-quantity=5.
|
30 | | Reference | Used for values that represent references between resources. For example an Observation resource will normally have a subject element which references a Patient resource for the patient that then Observation relates to. Can include :
|
31 | | Composite | Used in cases where a single search definition requires two or more values. SearchParameter values appear in the search request as a list of single values joined with a `$` character. Examples:
|
32 | | _filter | Used to specify a query expression that can be used in a Search operation. Example:
given eq "peter" and birthdate ge 2014-10-10
|
33 | | near | Used only with Location resource. Specifies a set of coordinates expressed as coordinates expressed as [latitude]\|[longitude]\|[distance]\|[units] |
34 |
35 | ## SearchParameter Modifiers
36 |
37 |
Modifiers may be specified as a suffix to the SearchParameter values and are separated by a colon.
38 |
|
43 | | String Parameter | :exact | Resources which have an exact match for the parameter, including case and character. |
44 | | Token Parameter | :text | Matches on text portion of CodeableConcept or Coding element. |
45 | | Token Parameter | :not | Match resources that do not have the code value. |
46 | | Token Parameter | :above | Match where coding subsumes the search code parameter. |
47 | | Token Parameter | :below | Match where coding is subsumed by the search code parameter. |
48 | | Token Parameter | :in | Match where coding is in a value set specified by the parameter. |
49 | | Token Parameter | :not-in | Match where coding is not in the value set specified by the parameter |
50 | | Token Parameter | :of-type | Match where identifier element is of specified type. |
51 | | Reference Parameter | :[type] | Specify the name of the resource type for reference |
52 | | Reference Parameter | :identifier | Search by identifier rather than literal reference. |
53 | | Reference Parameter | :above | Search for references in hierarchy |
54 | | Reference Parameter | :below | Search for references in hierarchy |
55 | | URI Parameter | :above | Partial matching (e.g. URLs that include a version number) |
56 | | URI Parameter | :below | Partial matching |
57 |
58 | ## SearchParameter Prefixes
59 |
60 |
Prefixes can be used to vary the type of matching done for ordered parameter types such as number, date and quantity:
GET [base]/Observation?_lastUpdated=gt2010-10-01
61 |
62 | | Operator | Description |
63 | |----------|---------------------------------------------------------------------------|
64 | | eq | Value in resource matches or is contained in value for parameter |
65 | | gt | Value in resource is greater than value in parameter. |
66 | | lt | Value in resource is less than value parameter. |
67 | | ge | Value in resource is greater than or equal to value in parameter. |
68 | | le | Value in resource is less than or equal to value in parameter. |
69 | | sa | Value in the resource starts after value in parameter. |
70 | | eb | Value in the resource ends before value in parameter. |
71 | | ap | Value in the resource is approximately the same as that in the parameter. |
72 |
73 |
74 | ## SearchParameter Resource
75 |
76 | 
77 |
78 | #### Required Elements
79 |
80 | | Element Name | Type | Description |
81 | |--------------|----------|-----------------------------------------------------------------|
82 | | url | uri | Canonical identifier for the resource |
83 | | name | string | Computer friendly name for the resource |
84 | | status | code | Status of the resource |
85 | | description | markdown | Natural language description for the search parameter |
86 | | code | code | Code used to reference the search parameter in a search request |
87 | | base | code | Resource type(s) that this search parameter applies to |
88 | | type | code | The data type for the search parameter value |
89 |
90 | #### Optional Elements
91 |
92 | | Element Name | Type | Description |
93 | |--------------|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
94 | | expression | string | FHIRPath expression used to extract an element from a resource.
Example: Condition.subject
|
95 | | xpath | string | XPath expression used to extract an element from a resource.
f:Condition/f:subject
|
96 | | multipleOr | boolean | Whether to allow multiple values (or) |
97 | | multipleAnd | boolean | Whether to allow multiple values (and) |
98 | | comparator | code | A list of one or more comparators that can be supported by the SearchParameter: eq \| ne \| gt \| lt \| ge \| le \| sa \| eb \| ap |
99 | | modifier | code | A list of one or more modifiers that can be supported by the SearchParameter: missing \| exact \| contains \| not \| text \| in \| not-in \| below \| above \| type \| identifier \| ofType |
100 | | chain | string | Names of one or more SearchParameters that will be chained together to form the current SearchParameter. |
101 | | component | BackboneElement | Used for composite SearchParameters. Defines each of the components that can be included in the SearchParameter type. Each component includes:
definition - a SearchParameter reference which defines this component works.
expression - a subexpression that defines how to retrieve the SearchParameter value for the definition from the parent SearchParameter’s value.
|
102 |
103 |
--------------------------------------------------------------------------------
/Search_References_ChainHasIncludeRevinclude/images/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Search_References_ChainHasIncludeRevinclude/images/graph.png
--------------------------------------------------------------------------------
/Search_References_ChainHasIncludeRevinclude/lesson.md:
--------------------------------------------------------------------------------
1 | # [FHIR Search: Chain, _has, _include & _revinclude](https://www.hl7.org/fhir/search.html)
2 |
3 | ## Overview
4 |
5 | Often times you’ll come across a scenario where you want to fetch not only one Resource, but Resources related to the core resource you’re working with. With FHIR, it’s possible to collect multiple resources in one call, potentially saving computational time. In this lesson, we’ll be going over the basics of chaining, “_has”, “_include” & “_revinclude”. We’ll start by describing how to use these for single relationships, and then describe how they work with nested relationships.
6 |
7 | If you want to try these queries on your FHIR server, attached is a [bundle](/examples/Search_References_ChainHasIncludeRevinclude/test-data-2.json) with sample test data to experiment with.
8 |
9 | For this topic, we will work with Specimen, Patient, and Organization resources. When reading through the query examples, refer to this diagram:
10 |
11 | 
12 |
13 | ## Single-Reference Queries
14 |
15 | We will start by focusing on a single arrow in the diagram above: the link from a Patient to its Organization via the Patients “organization” parameter.
16 |
17 |
18 | ### [Chain](https://www.hl7.org/fhir/search.html#chaining)
19 |
20 | A chain allows you to reduce the amount of search operations needed by “chaining” reference parameters in your API call, by appending a “.’ to a field, the name of a search parameter defined for the target resource. Consider the following query:
21 |
22 |
23 | ```url
24 | /Patient?organization._id=OR1
25 | ```
26 |
27 |
28 | In this query, we’re trying to capture all Patients who belong to Organization “OR1”. Taking a look at our diagram from earlier, we see that Patients PA1 and PA2 both belong to the Organization OR1 and so the expected results are:
29 |
30 | The expected results are: PA1, PA2.
31 |
32 |
33 | ### [Reverse Chain (_has)](https://www.hl7.org/fhir/search.html#has)
34 |
35 | “_has” works similarly to chaining, but in reverse - that is, selecting resources based on the properties of resources that refer to them. If you look at our diagram, you can see the flow that describes how one resource relates to another. With “_has”, take that same flow and reverse it.
36 |
37 |
38 | ```url
39 | /Organization?_has:Patient:organization:address-city=Kingston
40 | ```
41 |
42 |
43 | In this query, we are looking for all Organizations who have patients that live in Kingston. Note that we’re not concerned with the Patient resource in its entirety, we’re only concerned with the address-city part of the Patient resource.
44 |
45 | The expected results are: OR1.
46 |
47 |
48 | ### [Include (_include)](https://www.hl7.org/fhir/search.html#has)
49 |
50 | So far we’ve been looking at chaining queries to help slim down what results we’re trying to capture. With include, we’re not only capturing a particular resource type in our response, but also including resources related to it. This is particularly useful when you’re trying to capture multiple results without querying the server multiple times. Let’s look at the following query
51 |
52 |
53 | ```url
54 | /Patient?_id=PA1&_include=Patient:organization
55 | ```
56 |
57 |
58 | In this query, we want to return a Patient with an ID of PA1, and include all Organization resources it refers to.
59 |
60 | The expected results are: PA1, OR1
61 |
62 |
63 | ### [Reverse Include (_revinclude)](https://www.hl7.org/fhir/search.html#has)
64 |
65 | _revinclude is to _include what _has is to chaining. Namely it does the same thing but in reverse.
66 |
67 |
68 | ```url
69 | /Organization?_id=OR1&_revinclude=Patient:organization
70 | ```
71 |
72 |
73 | Here, we are requesting Organization OR1 along with all Patients that reference OR1 as their “organization”. Note that Organizations don’t point to Patients, but Patients point to Organizations and that is why we need to use _revinclude instead of _include here.
74 |
75 | The expected results are: OR1, PA1, PA2
76 |
77 |
78 | ## Nested Queries
79 |
80 | We will now expand our queries two levels deep, bringing Specimen into the picture. We are now querying across two relationships: a Specimen’s Patient via the “patient” parameter, as well at the Patient’s Organization via it’s “organization” parameter. We’ll follow the same order as above.
81 |
82 |
83 | ### Nested Chain
84 |
85 |
86 | ```url
87 | /Specimen?patient.organization._id=OR1
88 | ```
89 |
90 |
91 | In this query, we’re trying to capture all Specimens from Patients who belong to Organization “OR1”.
92 |
93 | The expected results are: SP1,SP2,SP3
94 |
95 |
96 | ### Nested Reverse Chain (_has)
97 |
98 | _has parameters require more information than chain parameters since you also need to know the resource type as well as the parameter that’s pointing to the resource you start with.
99 |
100 |
101 | ```url
102 | /Organization?_has:Patient:organization:_has:Specimen:patient:type=blood
103 | ```
104 |
105 |
106 | In this query, we are looking for all Organizations who have patients for which we have blood samples. With _has queries, you can start at the end and work your way backwards. In this case, we search for all specimens with type “blood” and then follow the “patient” of that specimen to go one level up. In this case, only one of our specimens, SP2, is a blood sample. Its patient is PA1. This patient now points us directly to its organization OR1 and that is our result.
107 |
108 | The expected results are: OR1.
109 |
110 | ### Nested _include
111 |
112 | You can also _include resources that are more than one reference away from your start resource:
113 |
114 |
115 | ```url
116 | /Specimen?_id=SP1&_include=Specimen:patient&_include:iterate=Patient:organization
117 | ```
118 |
119 |
120 | Here, we request Specimen SP1 and ask to include its Patient as well as that Patient’s Organization. Note the “:iterate” after the second include. This means also look inside other _included resources for the thing I’m asking for. For STU3, :recurse is used instead of :iterate.
121 |
122 | The expected results are: SP1, PA1, OR1
123 |
124 |
125 | ### Reverse Include (_revinclude)
126 |
127 | Similarly _revinclude can also include resources more than one away from your starting point:
128 |
129 |
130 | ```url
131 | /Organization?_id=OR1
132 | &_revinclude=Patient:organization
133 | &_revinclude:iterate=Specimen:patient
134 | ```
135 |
136 |
137 | Here, we are requesting Organization OR1 along with all Patients that reference OR1 as their “organization”. And we also ask for all Specimens that reference patients picked up by the first _revinclude.
138 |
139 | The expected results are: OR1, PA1, PA2, SP1, SP2, SP3
140 |
141 |
142 | ##
143 |
144 | The key takeway from all these queries is not just how to retrieve multiple resources at once, but their relationship to one another. That relationship helps dictate the type of queries you'll need to make to collect your data.
145 |
146 | 
147 |
148 | ##
149 |
150 | ## Exercise
151 |
152 | Find all Specimens whose Patients have a managingOrganization of OR1
153 |
154 |
155 | ```url
156 | /Specimen?patient.organization._id=OR1
157 | ```
158 |
159 |
160 | Expected response: PA1, PA2
161 |
162 | Find all Organizations who are referenced by a Patient that are referenced by a Specimen of type blood
163 |
164 |
165 | ```
166 | /Organization?_has:Patient:organization:_has:Specimen:patient:type=blood
167 | ```
168 |
169 |
170 | Expected response: OR1
171 |
172 | Find a Specimen with ID SP1, and include all Patients & the Organizations they reference. Note that you may need to use recurse (iterate) to solve this problem
173 |
174 |
175 | ```url
176 | /Specimen?_id=SP1&_include=Specimen:patient&_include:iterate=Patient:organization
177 | ```
178 |
179 |
180 | Expected response: SP1, PA1, OR1
181 |
182 | Find an Organization with ID OR1, and include all Patients
183 |
184 | STU3
185 |
186 |
187 | ```url
188 | /Organization?_id=OR1_revinclude=Patient:organization&_revinclude:recurse=Speciment:patient
189 | ```
190 |
191 |
192 | R4
193 |
194 |
195 | ```url
196 | /Organization?_id=OR1_revinclude=Patient:organization&_revinclude:iterate=Speciment:patient
197 | ```
198 |
199 |
200 | Expected response: OR1, PA1, PA2, SP1, SP2, SP3
201 |
--------------------------------------------------------------------------------
/Terminology/CodeSystem_and_ValueSet/lesson.md:
--------------------------------------------------------------------------------
1 | # Introduction to Terminology
2 |
3 | Many elements in the FHIR resources have a coded value: some fixed string (a sequence of characters) assigned elsewhere that identifies some defined “concept”.
4 | Using Codes in Resources (https://www.hl7.org/fhir/terminologies.html#4.1)
5 |
6 | “coded value” = “coded element” = “concept”
7 |
8 | ## For Clarity
9 |
10 | | General concepts | FHIR Resources |
11 | |-------------------|----------------|
12 | | code system | CodeSystem |
13 | | value set | ValueSet |
14 |
15 | ## Concept
16 |
17 | The general pattern for representing coded elements is using the following four elements:
18 |
19 | | | |
20 | |----------|--------------------------------------------------------------------------|
21 | | system | A URI that identifies the system |
22 | | version | Identifies the version of the system |
23 | | code | A string pattern that identifies a concept as defined by the code system |
24 | | display | A description of the concept as defined by the code system |
25 |
26 |
27 | “code” ≠ “concept”
28 |
29 | ## Example of a Concept
30 |
31 | The Coding data type represents this pattern.
32 |
33 | ```json
34 | {
35 | "system" : "http://loinc.org",
36 | "version" : "2.62",
37 | "code" : "55423-8",
38 | "display" : "Number of steps in unspecified time Pedometer"
39 | }
40 | ```
41 |
42 | ## Terminology Resources
43 |
44 | | | |
45 | |-----------------|-------------------------------------------|
46 | | CodeSystem - N | A list of codes defined by some authority |
47 | | ValueSet - N | A list of codes for a specific purpose |
48 | | ConceptMap - 3* | A list of code mappings |
49 |
50 | ## More Terminology Resources
51 |
52 | Out of scope:
53 |
54 | NamingSystem - 1*
55 |
56 | TerminologyCapabilities - 0*
57 |
58 | ## Relevant Data Types
59 |
60 | **code** - The instance represents the code only. The system is implicit - it is defined as part of the definition of the element, and not carried in the instance.
61 |
62 | **Coding** - A data type that has a code and a system element that identifies where the definition of the code comes from.
63 |
64 | **CodeableConcept** - A type that represents a concept by plain text and/or one or more coding elements.
65 |
66 | **Quantity** - The instance has system and code elements for carrying a code for the type of unit, and these can be bound to a value set.
67 |
68 | **string** - The instance carries a string. In some cases, applications may wish to control the set of valid strings for a particular element, so the string value can be treated as a coded element (like code).
69 |
70 | **uri** - Like string, URIs can be treated as a coded element.
71 |
72 | # CodeSystem
73 |
74 | ## CodeSystem
75 |
76 | * Has an identifying URL (e.g. http://loinc.orc)
77 | * Contains a set of codes
78 | * May contain hierarchies
79 | * E.g. “HB” and “WBC” are children of “HEMO”
80 | * May contain properties
81 | * E.g. loinc codes contain properties such as “STATUS” and “METHOD”
82 | * May be defined by standards bodies (e.g. HL7 or LOINC) or by individuals
83 |
84 | ## Codes in a CodeSystem
85 |
86 | * Each code in a system has the following things:
87 | * System: http://loinc.org
88 | * Code: 718-7
89 | * Display: Hemoglobin [Mass/volume] in Blood
90 | * Codes may also have properties and children
91 |
92 | ## CodeSystem Required Elements
93 |
94 | | Element Name | Type | Description |
95 | |--------------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
96 | | status | code | Status of the resource: draft \| active \| retired \| unknown |
97 | | content | code | A code that indicates the extent that the content of the code system (the concepts and codes it defines) are represented in this resource instance: not-present \| example \| fragment \| complete \| supplement |
98 |
99 | ## CodeSystem Optional Elements
100 |
101 | | Element Name | Type | Description |
102 | |------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
103 | | url | uri | The canonical URL that never changes for this code system. This canonical URL is used to refer to all instances of this particular code system across all servers and systems. Ideally, should be a URL which resolves to the location of the master version of the code system. |
104 | | version | string | Indicates a version for the CodeSystem resource.|
105 | | versionNeeded | boolean | Indicates whether a version is required (i.e. if CodeSystem definition is not stable) |
106 | | publisher | String | Name of the publisher for CodeSystem |
107 | | contact | ContactDetail | Contact details for publisher |
108 | | useContext | usageContext | The context that the content is intended to support |
109 | | jurisdiction | CodeableConcept | Intended jurisdiction for the code system. |
110 | | purpose | markdown | Why this code system is defined. |
111 | | copyright | markdown | Use and/or publishing restrictions |
112 | | hierarchyMeaning | code | If the code system a hierarchy of codes, describes the meaning of the relationships between parent and child codes: grouped-by \| is-a \| part-of \| classified-with |
113 | | compositional | boolean | Flag indicating whether the code system describes a compositional grammar. |
114 | | concept | BackboneElement | Definitions for one or more concepts that are included in the code system. Each concept component includes:
code - a string code value
display - a string display value for the concept.
definition - a formal definition for the concept.
designation - one or more BackboneElement elements providing other representations for the concept (e.g. different languages)
property - one or more BackboneElement elements used to describe a specific property of the concept.
|
115 |
116 | ## CodeSystem $lookup Operation
117 |
118 | Given a code/system, or a Coding, get additional details about the concept, including definition, status, designations, and properties.
119 |
120 | | In Parameter | Type | Description |
121 | |------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
122 | | code | code | The code to lookup. If a code is provided, a system must be provided. |
123 | | system | uri | The system for the code that is to be located. |
124 | | version | string | The version of the system, if one was provided in the source data. |
125 | | coding | Coding | A coding to look up. |
126 | | date | dateTime | The date for which the information should be returned. |
127 | | displayLanguage | code | The requested language for display (language as defined in the concept designation element). |
128 | | property | code | A property that the client wishes to be returned in the output. If no properties are specified, the server chooses what to return. |
129 |
130 | ## CodeSystem $validate-code Operation
131 |
132 | Validate that a coded value is in the code system. The operation returns a result (true / false), an error message, and the recommended display for the code.
133 |
134 | | In Parameter | Type | Description |
135 | |------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
136 | | url | uri | The CodeSystem URL. |
137 | | version | string | The version of the system, if one was provided in the source data. |
138 | | code | code | The code to be validated. |
139 | | coding | coding | A coding to validate. The system must match the specified code system. |
140 | | codeableConcept | CodeableConcept | A full codeableConcept to validate. |
141 | | codeSystem | CodeSystem | The codeSystem is provided directly as part of the request. |
142 | | display | string | The display associated with the code, if provided. |
143 | | date | dateTime | The date for which the validation should be checked.
144 | | abstract | boolean | If this parameter has a value of true, the client is stating that the validation is being performed in a context where a concept designated as 'abstract' is appropriate/allowed to be used, and the server should regard abstract codes as valid. If this parameter is false, abstract codes are not considered to be valid. |
145 |
146 | ## CodeSystem $subsumes Operation
147 |
148 | Test the subsumption relationship between code/Coding A and code/Coding B given how the concepts are defined in the underlying code system and how parent/child relationships are defined in the CodeSystem (see hierarchyMeaning).
149 |
150 | Operation returns an outcome which includes one of the following codes:
151 |
152 | * equivalent
153 | * subsumes
154 | * subsumed-by
155 | * not-subsumed
156 |
157 | | In Parameter | Type | Description |
158 | |------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
159 | | codeA | code | The "A" code that is to be tested. |
160 | | codeB | code | The "B" code that is to be tested. |
161 | | system | uri | The code system in which subsumption testing is to be performed. |
162 | | version | string | The version of the system, if one was provided in the source data |
163 | | codingA | coding | The "A" Coding that is to be tested. |
164 | | codingB | coding | The "B" Coding that is to be tested. |
165 |
166 | # ValueSet
167 |
168 | Where a code system is a list of codes defined by some authority, a value set is a list of codes for a specific purpose.
169 |
170 | A ValueSet resource instance specifies a set of codes drawn from one or more code systems, intended for use in a particular context.
171 |
172 | This list can be include all of the codes from a given code system, only some of the codes from a given code system, and even codes from multiple code systems as illustrated in the diagram below.
173 |
174 | 
175 |
176 |
177 | ## Two Aspects of a ValueSet
178 |
179 | * compose - A definition of which codes are intended to be in the value set (“intension”).
180 | * expansion - The list of codes that are actually in the value set under a given set of conditions (“extension”).
181 |
182 | ## Binding Strengths
183 |
184 | **required** - To be conformant, the concept in this element SHALL be from the specified value set.
185 |
186 | **extensible** - To be conformant, the concept in this element SHALL be from the specified value set if any of the codes within the value set can apply to the concept being communicated. If the value set does not cover the concept (based on human review), alternate codings (or, data type allowing, text) may be included instead.
187 |
188 | **preferred** - Instances are encouraged to draw from the specified codes for interoperability purposes but are not required to do so to be considered conformant.
189 |
190 | **example** - Instances are not expected or even encouraged to draw from the specified value set. The value set merely provides examples of the types of concepts intended to be included.
191 |
192 | ## ValueSet Operation: $expand
193 |
194 | Follow the composition rules in the ValueSet and return the complete set.
195 |
196 | Example:
197 |
198 | https://try.smilecdr.com:8000/baseR4/CodeSystem?url=http://hl7.org/fhir/administrative-gender
199 |
200 | https://try.smilecdr.com:8000/baseR4/ValueSet?url=http://hl7.org/fhir/ValueSet/administrative-gender
201 |
202 | https://try.smilecdr.com:8000/baseR4/ValueSet/$expand?url=http://hl7.org/fhir/ValueSet/administrative-gender
203 |
204 | ## ValueSet Operation: $validate-code
205 |
206 | Validate that a coded value is in the set of codes allowed by a value set.
207 |
208 | Example:
209 |
210 | https://try.smilecdr.com:8000/baseR4/ValueSet/$validate-code?url=http://hl7.org/fhir/ValueSet/administrative-gender&system=http://hl7.org/fhir/administrative-gender&code=female
211 |
--------------------------------------------------------------------------------
/Transactions/img/bundle-types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Transactions/img/bundle-types.png
--------------------------------------------------------------------------------
/Transactions/img/fhir-bundle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Transactions/img/fhir-bundle.png
--------------------------------------------------------------------------------
/Transactions/img/paging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hapifhir/fhir-tutorial/0f64c6fdfc24752a591d870cdb98554ab8a754b0/Transactions/img/paging.png
--------------------------------------------------------------------------------
/Transactions/lesson.md:
--------------------------------------------------------------------------------
1 | # FHIR Transactions
2 |
3 | ## Overview
4 |
5 | Bundles are core to transactions. As a front end dev, I frequently come across them when consuming data to show in a view from a fhir API endpoint, but what are they really?
6 |
7 | ## Bundles
8 |
9 | > "A common operation performed with resources is to gather a collection of them into a single instance > with containing context... In FHIR this is referred to as "bundling" the resources together."
10 | *"Resource Bundle - Content"*, [HL7](https://www.hl7.org/fhir/bundle.html)
11 |
12 | Bundles act like a container for a set of independent FHIR resources. They allow us to group and transmit resources across API requests. I want to emphasize the independent nature of resources in bundles, as opposed to “contained resources”. Contained resources are embedded "in" the container resource. And they can't be requested, updated or deleted separately, or referenced individually from outside its containing resource. On the other hand, resources inside a Bundle get created individually on the server and thus can be accessed via REST api, and acted on via CRUD operations.
13 |
14 | 
15 |
16 | 1. Metadata describing the Bundle type-which would include the total amount of entries if it’s a searchset- and a link if you need to retrieve it later.
17 | 1. Entry: where the resources that the Bundle has are stored. This also includes URLs which you can use to retrieve the resource individually.
18 | 1. Request property: Used when you're uploading Bundles - and where you specify to the server what to do with each resource.
19 | 1. Response: Used by the server when it's responding to your request - it tells you how each operation went.
20 |
21 | Resource bundles can be used to:
22 | - Find resources that meet some criteria (as in a searchset)
23 | - Find the version of some resources as part of a `_history` operation
24 | - Send messages with resources from app to app ([FHIR Messaging](https://www.hl7.org/fhir/messaging.html))
25 | - Grouping resources as exchangeable and persistable [documents](https://www.hl7.org/fhir/documents.html)
26 | - CRUD-ing resources in a single operation
27 | - Storing a collection of resources
28 |
29 |
30 | ## Types of Bundles
31 |
32 | #### Searchsets
33 | The Bundle collates search results into a single response. As some search results can return a large number of results, and paging separates them into manageable blocks.
34 |
35 | #### Document
36 | A document is an immutable bundle set of resources with a fixed presentation that is authored and attested by humans, organizations and devices. The first resource is Composition.
37 |
38 | #### Messages
39 | In FHIR messaging, a "request message" is sent from a application to another application when an event happens. The request message consists of a Bundle identified by the type "message", with the first resource in the bundle being a MessageHeader resource. The MessageHeader resource has a code - the message event - that identifies the nature of the request message, and it also carries request metadata. The other resources in the bundle depend on the type of the request.
40 |
41 | #### History
42 | This is similar to searchset, but is specialised for `_history` operations, for example, looking at all the edits made to a single Patient resource.
43 |
44 | 
45 |
46 | L: Transaction Bundles
47 | The `entry.request` and `entry.response` property is required for batch, transaction, history and their respective responses.
48 | A fullUrl must be unique in a bundle, or else entries with the same fullUrl must have different meta versionId (except in history bundles).
49 |
50 | C:
51 | A bundle of a searchset for all the Officer Jenny Practitioner elements I put into try.smilecdr.com database. The entry has search property only when it's a search
52 |
53 |
54 | R: A bundle of resources constituting a FHIR Document
55 | A document must have an identifier with a system and a value, a date, and Composition as the first resource. It also has required references such as a subject, encounter, and author.
56 |
57 | #### Operation Outcome
58 |
59 | Operation Outcomes are returned as the content of a transaction response. They are a FHIR resource with sets of error, warning and information messages describing the success or failure of an action.
60 |
61 | How are they used?
62 |
63 | - When a REST operation fails
64 | - As the response on a validation operation to provide information about the outcome
65 | - As part of a message response, if it hasn’t been processed correctly
66 | - As the response to a batch/transaction, when requested
67 | - As part of a search's Bundle response containing information about the search
68 |
69 | Operation outcomes that are returned should match the status of the HTTP response code, and should include at least one issue object.
70 |
71 | For example, operation outcomes that are successful would accompany an HTTP response status code of 201 for newly created resources, 204 for successful deletion, or 200 for successful `GET` requests.
72 |
73 | In this example, I successfully deleted the 8th version of Jenny on try.smilecdr.com.
74 |
75 | ##### Success
76 | ```
77 | {
78 | "resourceType": "OperationOutcome",
79 | "issue": [
80 | {
81 | "severity": "information",
82 | "code": "informational",
83 | "diagnostics": "Successfully deleted 1 resource(s) in 24ms"
84 | }
85 | ]
86 | }
87 | ```
88 |
89 | ##### Failure
90 | ```
91 | { "resourceType": "OperationOutcome",
92 | "issue": [
93 | {
94 | "severity": "error",
95 | "code": "processing",
96 | "diagnostics": "Unknown resource type 'Patients' - Server knows how to handle: [Appointment, Account, Invoice, CatalogEntry, EventDefinition, DocumentManifest, MessageDefinition, Goal, MedicinalProductPackaged, Endpoint, EnrollmentRequest, Consent, CapabilityStatement, Measure…]”
97 | }
98 | ]
99 | }
100 | ```
101 | I got this example from try.smilecdr.com by querying `Patients` instead of `Patient` when trying to find all the patients on the server.
102 | The accompanying HTTP status codes for failing operations would be 404 for "Not Found" or 422 for "Unprocessable Entity", which is thrown when an object you post violates FHIR standards.
103 |
104 | ## History
105 |
106 | The history interaction retrieves the history of either a resource, all resources of a given type, or all resources supported by the system.
107 | Create, Update, Delete actions can create history entries, and have side effects on the `meta.versionId`.
108 | As a result of instance creation, the `response.lastModified` property will always matches `the meta.lastUpdated`.
109 |
110 |
111 | On success, the response body will contain a JSON-encoded representation of a history bundle with the version history sorted from most recent to the oldest version.
112 |
113 | Errors generated by the FHIR store have a JSON-encoded OperationOutcome describing the issue for the error.
114 |
115 | When the Bundle is too big to send in one go, it may have too resources within it or too many to send in one response, and the server will break it up into smaller pieces (called "pages"). To allow for easy navigation from one page to the next the Bundle provides links that set the context for navigating to the next page within it. In addition, there are also links to the previous, first, and last pages provided in each Bundle.
116 |
117 | For example, if a search returns 500 resources, the server can return a bundle containing only the first 20 and a link which will return the next 20, and so on until the end.
118 |
119 | 
120 |
121 | ## Batch and Transactions
122 |
123 | Transactions are complex interactions. It's not expected that every server will implement them, and the server should be configured to do so. Servers that don’t support it will just return a HTTP 400 error, which might include an `OperationOutcome`
124 |
125 | Transactions update, create or delete a set of resources as a single transaction.
126 | ```
127 | "interaction": [
128 | {
129 | "code": "history-system"
130 | },
131 | {
132 | "code": "transaction"
133 | }
134 | ],
135 | ```
136 |
137 | Batch transactions perform a set of a separate interactions in a single HTTP operation.
138 |
139 | `search-system` searches all resources based on some filter criteria.
140 |
141 | ```
142 | "interaction": [
143 | {
144 | "code": "history-system"
145 | },
146 | {
147 | "code": "transaction"
148 | }
149 | ],
150 | ```
151 |
152 | Batch and Transaction interactions submit a set of actions to perform on a server in a single HTTP request/response.
153 |
154 | Multiple actions on multiple resources of the same or different types may be submitted
155 | They may be a mix of interactions like read, search, create, update, delete, etc.
156 |
157 | #### Batch vs. Transaction: what's the difference?
158 |
159 | ##### Batch
160 | - The actions may be performed independently as a "batch"
161 | - Each entry is treated as if an individual interaction or operation
162 |
163 | ##### Transaction
164 | - A single atomic "transaction" where the entire set of changes is treated as a single entity
165 | - All interactions or operations either succeed or fail together
166 |
167 | ### How Do We Perform That?
168 |
169 | Batch or Transaction is done with an HTTP `POST` command. The Content is a Bundle with `Bundle.type` set to "batch" or "transaction". Each Bundle entry contains the request details.
170 | For `PUT` or `POST`, it also contains the resource.
171 |
172 | A batch:
173 | ```
174 | {
175 | "resourceType": "Bundle",
176 | "id": "bundle-request-simplesummary",
177 | "type": "batch",
178 | "entry": [
179 | {
180 | "request": {
181 | "method": "GET",
182 | "url": "Patient/8675309"
183 | }
184 | },
185 | {
186 | "request": {
187 | ...
188 | }
189 | },
190 |
191 | ...
192 |
193 | ]
194 | }
195 | ```
196 |
197 | A transaction:
198 | ```
199 | {
200 | "resourceType": "Bundle",
201 | "id": "bundle-transaction",
202 | "type": "transaction",
203 | "entry": [
204 | {
205 | "fullUrl":
206 | "http://example.org/fhir/Patient/123",
207 | "resource": {
208 | "resourceType": "Patient",
209 | "id": "123",
210 | "active": true,
211 | "name": [
212 | {
213 | "use": "official",
214 | "family": "Chalmers",
215 | "given": [
216 | "Peter",
217 | "James"
218 | ]
219 | }
220 | ],
221 | "gender": "male",
222 | "birthDate": "1974-12-25"
223 | },
224 | "request": {
225 | "method": "PUT",
226 | "url": "Patient/123"
227 | }
228 | },
229 | ...
230 | ]
231 | }
232 | ```
233 |
234 | ### Batch Processing Rules
235 |
236 | - You can't have interdependencies between the different entries in the same Bundle.
237 | - Success or failure of one change should not alter the success or failure or resulting content of another change, and the server will validate that.
238 | - The order of execution is the same as for Transactions...but that shouldn’t matter because you followed all the above rules like a good developer!
239 |
240 | ### Did it Work?
241 |
242 | If the HTTP response code is `200 OK`, the batch was processed correctly regardless of the success of the operations within the Batch!
243 | To see the status of the operations, look inside the returned Bundle.
244 | A response code on an entry of other than `2xx` indicates that processing the request in the entry failed.
245 |
246 | ### Transaction Processing Rules
247 |
248 | #### It’s all or Nothing
249 | For transactions, there are only two outcomes:
250 | - Either: Every action within succeeds. Servers accepts all actions and returns a `200 OK`, along with a response bundle
251 | - Or: All actions are rejected. Server returns a HTTP `400` or `500` type response
252 |
253 | ### Order of Operations
254 | Order of the entries in the Bundle doesn’t matter!
255 | Either way, the actions are processed by the server in this order:
256 |
257 | 1. Process any `DELETE` interactions
258 | 1. Process any `POST` interactions
259 | 1. Process any `PUT` or `PATCH` interactions
260 | 1. Process any `GET` or `HEAD` interactions
261 | 1. Resolve any conditional references
262 |
263 | #### Internal References
264 | - A transaction may include references from one resource to another in the bundle
265 | - When the server assigns a new id to any resource in the bundle, it also updates any references to that resource in the same bundle as they are processed
266 | - References to resources that are not part of the bundle are left untouched
267 |
268 | #### Conditional References
269 | Sometimes you want to perform a set of operations involving resources that the server doesn’t know about yet.
270 |
271 | In a `POST` request
272 | ```
273 | {
274 | "resourceType": "Patient",
275 | "identifier": [ { "system":
276 | "urn:oid:1.2.36.146.595.217.0.1",
277 | "value": "12345" } ],
278 | "name": [ {
279 | "family": "Iantorno",
280 | "given": [ "Mark", "Brent",
281 | "Bahlai" ]
282 | } ],
283 | "gender": "male",
284 | "birthDate": "1983-06-23"
285 | }
286 | ```
287 |
288 | And its response `201 Created`:
289 | ```
290 | {
291 | "resourceType": "Patient",
292 | "id": "1625",
293 | "meta": {
294 | "versionId": "1",
295 | "lastUpdated": "2020-05-23T09:21:26.065-04:00"
296 | },
297 | "identifier": [
298 | {
299 | "system": "urn:oid:1.2.36.146.595.217.0.1",
300 | "value": "12345"
301 | }
302 | ],
303 | "name": [
304 | {
305 | "family": "Iantorno",
306 | "given": [
307 | "Mark",
308 | "Brent",
309 | "Bahlai"
310 | ]
311 | }
312 | ],
313 | "gender": "male",
314 | "birthDate": "1974-12-25"
315 | }
316 | ```
317 |
318 | If we then `GET` the same resource:
319 | ```
320 | {
321 | "resourceType": "Bundle",
322 | "id": "8b5be330-6138-4894-a3ea-187c7acd010c",
323 | "meta": {
324 | "lastUpdated": "2020-05-23T10:06:11.622-04:00"
325 | },
326 | "type": "searchset",
327 | "total": 12,
328 | "link": [
329 | {
330 | "relation": "self",
331 | "url": "http://localhost:8000/Patient"
332 | }
333 | ],
334 | "entry": [
335 | {
336 | "fullUrl": "http://localhost:8000/Patient/1625",
337 | "resource": {
338 | "resourceType": "Patient",
339 | "id": "1625",
340 | ...
341 | },
342 | "search": {
343 | "mode": "match"
344 | }
345 | },
346 | ...
347 | ]
348 | }
349 | ```
350 |
351 | ##### What is a Conditional Reference?
352 |
353 | When a client is making a bundle, you might not know the logical id of a resource but you know identifying information.
354 | You resolve that identifier to a logical id many ways but it requires an additional REST transaction to the commit.
355 |
356 | ##### How does it resolve?
357 |
358 | In a transaction (and only transactions), references to resources may be replaced by a search URI that describes how to find the correct reference.
359 | It checks all references for search URIs, and uses the search to locate matching resources.
360 | If there are no matches, or multiple matches, the transaction fails, and an error is returned to the user.
361 | If there is a single match, the server replaces the search URI with a reference to the matching resource.
362 |
--------------------------------------------------------------------------------
/examples/Search_References_ChainHasIncludeRevinclude/FHIR_Tutorial_Series_FHIR_Search_References_Flow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/Search_References_ChainHasIncludeRevinclude/test-data-1.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "resourceType": "Bundle",
4 | "id": "bundle-transaction",
5 | "type": "transaction",
6 | "entry": [
7 | {
8 | "resource": {
9 | "resourceType": "Practitioner",
10 | "id": "P1",
11 | "name": [
12 | {
13 | "family": "Seuss"
14 | }
15 | ]
16 | },
17 | "request": {
18 | "method": "PUT",
19 | "url": "Practitioner/P1"
20 | }
21 | },
22 | {
23 | "resource": {
24 | "resourceType": "Practitioner",
25 | "id": "P2",
26 | "name": [
27 | {
28 | "family": "Doolittle"
29 | }
30 | ]
31 | },
32 | "request": {
33 | "method": "PUT",
34 | "url": "Practitioner/P2"
35 | }
36 | },
37 | {
38 | "resource": {
39 | "resourceType": "HealthcareService",
40 | "id": "HS1",
41 | "type": {
42 | "coding": [
43 | {
44 | "system": "http://try.smilecdr.com/lunch_and_learn",
45 | "code": "Physio"
46 | }
47 | ]
48 | }
49 | },
50 | "request": {
51 | "method": "PUT",
52 | "url": "HealthcareService/HS1"
53 | }
54 | },
55 | {
56 | "resource": {
57 | "resourceType": "HealthcareService",
58 | "id": "HS2",
59 | "type": {
60 | "coding": [
61 | {
62 | "system": "http://try.smilecdr.com/lunch_and_learn",
63 | "code": "Massage"
64 | }
65 | ]
66 | }
67 | },
68 | "request": {
69 | "method": "PUT",
70 | "url": "HealthcareService/HS2"
71 | }
72 | },
73 | {
74 | "resource": {
75 | "resourceType": "HealthcareService",
76 | "id": "HS3",
77 | "type": {
78 | "coding": [
79 | {
80 | "system": "http://try.smilecdr.com/lunch_and_learn",
81 | "code": "Chiro"
82 | }
83 | ]
84 | }
85 | },
86 | "request": {
87 | "method": "PUT",
88 | "url": "HealthcareService/HS3"
89 | }
90 | },
91 | {
92 | "resource": {
93 | "resourceType": "PractitionerRole",
94 | "id": "PR1",
95 | "practitioner": {
96 | "reference": "Practitioner/P1"
97 | },
98 | "healthcareService": {
99 | "reference": "HealthcareService/HS1"
100 | }
101 | },
102 | "request": {
103 | "method": "PUT",
104 | "url": "PractitionerRole/PR1"
105 | }
106 | },
107 | {
108 | "resource": {
109 | "resourceType": "PractitionerRole",
110 | "id": "PR2",
111 | "practitioner": {
112 | "reference": "Practitioner/P1"
113 | },
114 | "healthcareService": {
115 | "reference": "HealthcareService/HS2"
116 | }
117 | },
118 | "request": {
119 | "method": "PUT",
120 | "url": "PractitionerRole/PR2"
121 | }
122 | },
123 | {
124 | "resource": {
125 | "resourceType": "PractitionerRole",
126 | "id": "PR3",
127 | "practitioner": {
128 | "reference": "Practitioner/P2"
129 | },
130 | "healthcareService": {
131 | "reference": "HealthcareService/HS1"
132 | }
133 | },
134 | "request": {
135 | "method": "PUT",
136 | "url": "PractitionerRole/PR3"
137 | }
138 | }
139 | ]
140 | }
--------------------------------------------------------------------------------
/examples/Search_References_ChainHasIncludeRevinclude/test-data-2.json:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "Bundle",
3 | "type": "transaction",
4 | "entry": [
5 | {
6 | "resource": {
7 | "resourceType": "Patient",
8 | "id": "PA1",
9 | "address": [
10 | {
11 | "city": "Toronto",
12 | "state": "ON",
13 | "country": "Canada"
14 | }
15 | ],
16 | "managingOrganization": {
17 | "reference": "Organization/OR1"
18 | }
19 | },
20 | "request": {
21 | "method": "PUT",
22 | "url": "Patient/PA1"
23 | }
24 | },
25 | {
26 | "resource": {
27 | "resourceType": "Patient",
28 | "id": "PA2",
29 | "address": [
30 | {
31 | "city": "Kingston",
32 | "state": "ON",
33 | "country": "Canada"
34 | }
35 | ],
36 | "managingOrganization": {
37 | "reference": "Organization/OR1"
38 | }
39 | },
40 | "request": {
41 | "method": "PUT",
42 | "url": "Patient/PA2"
43 | }
44 | },
45 | {
46 | "resource": {
47 | "resourceType": "Patient",
48 | "id": "PA3",
49 | "address": [
50 | {
51 | "city": "Guelph",
52 | "state": "ON",
53 | "country": "Canada"
54 | }
55 | ],
56 | "managingOrganization": {
57 | "reference": "Organization/OR2"
58 | }
59 | },
60 | "request": {
61 | "method": "PUT",
62 | "url": "Patient/PA3"
63 | }
64 | },
65 | {
66 | "resource": {
67 | "resourceType": "Organization",
68 | "id": "OR1"
69 | },
70 | "request": {
71 | "method": "PUT",
72 | "url": "Organization/OR1"
73 | }
74 | },
75 | {
76 | "resource": {
77 | "resourceType": "Organization",
78 | "id": "OR2"
79 | },
80 | "request": {
81 | "method": "PUT",
82 | "url": "Organization/OR2"
83 | }
84 | },
85 | {
86 | "resource": {
87 | "resourceType": "Specimen",
88 | "id": "SP1",
89 | "subject": {
90 | "reference": "Patient/PA1"
91 | },
92 | "type": {
93 | "coding": [
94 | {
95 | "system": "http://snomed.info/sct",
96 | "code": "386045008",
97 | "display": "Hair structure (body structure)"
98 | }
99 | ]
100 | }
101 | },
102 | "request": {
103 | "method": "PUT",
104 | "url": "Specimen/SP1"
105 | }
106 | },
107 | {
108 | "resource": {
109 | "resourceType": "Specimen",
110 | "id": "SP2",
111 | "subject": {
112 | "reference": "Patient/PA1"
113 | },
114 | "type": {
115 | "coding": [
116 | {
117 | "system": "http://snomed.info/sct",
118 | "code": "87612001",
119 | "display": "Blood (substance)"
120 | }
121 | ]
122 | }
123 | },
124 | "request": {
125 | "method": "PUT",
126 | "url": "Specimen/SP2"
127 | }
128 | },
129 | {
130 | "resource": {
131 | "resourceType": "Specimen",
132 | "id": "SP3",
133 | "subject": {
134 | "reference": "Patient/PA2"
135 | },
136 | "type": {
137 | "coding": [
138 | {
139 | "system": "http://snomed.info/sct",
140 | "code": "39937001",
141 | "display": "Skin structure (body structure)"
142 | }
143 | ]
144 | }
145 | },
146 | "request": {
147 | "method": "PUT",
148 | "url": "Specimen/SP3"
149 | }
150 | },
151 | {
152 | "resource": {
153 | "resourceType": "Specimen",
154 | "id": "SP4",
155 | "subject": {
156 | "reference": "Patient/PA3"
157 | },
158 | "type": {
159 | "coding": [
160 | {
161 | "system": "http://snomed.info/sct",
162 | "code": "39937001",
163 | "display": "Skin structure (body structure)"
164 | }
165 | ]
166 | }
167 | },
168 | "request": {
169 | "method": "PUT",
170 | "url": "Specimen/SP4"
171 | }
172 | }
173 | ]
174 | }
--------------------------------------------------------------------------------