The FHIR Specification defines two resource types that are used as a part of defining and using codes:
ValueSets are defined by a collection of rules (the composition). These rules can be simple inclusion rules (e.g. "include codes A, B, and C") or much more complex rules (e.g. "include any codes that are a child of code A", or "include codes with a specific property value", etc).
When a ValueSet is uploaded into Smile CDR (e.g. a complete and valid resource of type ValueSet is created in the FHIR repository), Smile CDR will schedule a background job to calculate the expansion and store it in a dedicated set of database tables. Using this pre-calculated expansion has several advantages:
When you perform a ValueSet expansion on a previously stored ValueSet, an extension will be added to the ValueSet.meta
element. This extension shows the status of the pre-calculation. If the pre-calculation has not yet been completed, you will see a response similar to the following:
To test whether a ValueSet has been pre-calculated, simply request the expansion using the $expand
operation. For example, the following request can be used to request the expansion of the LOINC ValueSet:
GET ValueSet/$expand?url=http://loinc.org/vs
If this ValueSet has not been precalculated, a response resembling the following will be produced.
{
"resourceType": "ValueSet",
"meta": {
"extension": [ {
"url": "http://hapifhir.io/fhir/StructureDefinition/valueset-expansion-message",
"valueString": "ValueSet \"ValueSet.url[http://example.com/my_value_set]\" has not yet been pre-expanded. Performing in-memory expansion without parameters. Current status: NOT_EXPANDED | The ValueSet is waiting to be picked up and pre-expanded by a scheduled task."
} ]
},
"status": "active",
[ ... Remaining Fields Not Shown ... ]
}
After the pre-calculation has completed, you will see a response similar to the following:
{
"resourceType": "ValueSet",
"meta": {
"extension": [ {
"url": "http://hapifhir.io/fhir/StructureDefinition/valueset-expansion-message",
"valueString": "ValueSet was expanded using an expansion that was pre-calculated at 2021-09-21T14:11:12.324-04:00"
} ]
},
"status": "active",
[ ... Remaining Fields Not Shown ... ]
}
Any time that a ValueSet resource is updated in the database in a way that causes the version number to be incremented, any previously calculated expansion is immediately invalidated and will no longer be used by the system. A new scheduled task is immediately created that will re-calculate the expansion in the background. Until this re-calculation is complete, any expansion requests or code validation requests against this ValueSet will be perfomed using an in-memory expansion.
It is also possible to manually request that the existing pre-calculated expansion be invalidated and a new one calculated. This is useful in cases where the underlying CodeSystem has been changed in a meaningful way.
To invalidate an existing Pre-Calculated expansion, use the $invalidate-expansion
operation by issuing a POST against the ValueSet resource ID. For example:
POST ValueSet/my-valueset/$invalidate-expansion
Many CodeSystem resources define Concepts in a hierarchy. For example, a fictitious "Animals" CodeSystem might define a code "Pets" with child codes "Dogs" and "Cats".
The hierarchy in a CodeSystem often indicates an "is-a" relationship between the parent code and the child codes. This is not always the case; the hierarchy can imply different kinds of relationships depending on the specific system.
ValueSets can be used to retrieve all of the codes that are a child of a specific code in a CodeSystem. For example, suppose you have the following CodeSystem. Note how there are two codes at the root level ("A" and "B") and each of these codes have children, some of which have further children.
{
"resourceType": "CodeSystem",
"url": "http://example.com/my_code_system",
"content": "complete",
"concept": [ {
"code": "A",
"display": "Code A",
"concept": [ {
"code": "AA",
"display": "Code AA",
"concept": [ {
"code": "AAA",
"display": "Code AAA"
} ]
}, {
"code": "AB",
"display": "Code AB"
} ]
}, {
"code": "B",
"display": "Code B",
"concept": [ {
"code": "BA",
"display": "Code BA"
}, {
"code": "BB",
"display": "Code BB"
} ]
} ]
}
The hierarchy for the codes above can be visualized as follows:
|-- A | |-- AA | | \-- AAA | \-- AB \-- B |-- BA \-- BB
To create a ValueSet containing all of the children of a specific code in this CodeSystem, a ValueSet with a filter can be defined:
{
"resourceType": "ValueSet",
"url": "http://example.com/my_value_set",
"status": "active",
"compose": {
"include": [ {
"system": "http://example.com/my_code_system",
"filter": [ {
"property": "concept",
"op": "is-a",
"value": "A"
} ]
} ]
}
}
Note that the "is-a" filter will exclude the concept itself. The following example combines an "is-a" filter with a simple explcit code inclusion in order to include the code "A" as well as all of its descendents.
{
"resourceType": "ValueSet",
"url": "http://example.com/my_value_set",
"status": "active",
"compose": {
"include": [ {
"system": "http://example.com/my_code_system",
"filter": [ {
"property": "concept",
"op": "is-a",
"value": "A"
} ]
}, {
"system": "http://example.com/my_code_system",
"concept": [ {
"code": "A"
} ]
} ]
}
}
Performing a ValueSet expansion is as simple as invoking an HTTP POST on the following URL:
http://[server-base-url]/ValueSet/$expand
This will produce the following response. Note that the hierarchy is not included in the response.
{
"resourceType": "ValueSet",
"status": "active",
"compose": {
"include": [ {
"system": "http://example.com/my_code_system",
"filter": [ {
"property": "concept",
"op": "is-a",
"value": "A"
} ]
}, {
"system": "http://example.com/my_code_system",
"concept": [ {
"code": "A"
} ]
} ]
},
"expansion": {
"identifier": "dcd5e662-bd53-4137-a0af-55771e37b3cb",
"timestamp": "2021-04-06T14:38:39-04:00",
"total": 4,
"offset": 0,
"parameter": [ {
"name": "offset",
"valueInteger": 0
}, {
"name": "count",
"valueInteger": 1000
} ],
"contains": [ {
"system": "http://example.com/my_code_system",
"code": "AB",
"display": "Code AB"
}, {
"system": "http://example.com/my_code_system",
"code": "AA",
"display": "Code AA"
}, {
"system": "http://example.com/my_code_system",
"code": "AAA",
"display": "Code AAA"
}, {
"system": "http://example.com/my_code_system",
"code": "A",
"display": "Code A"
} ]
}
}
If you would like the parent-child relationships to be reflected in the response, you can add the includeHierarchy
parameter in your request. For example:
http://[server-base-url]/ValueSet/$expand
This will produce the following response:
{
"resourceType": "ValueSet",
"status": "active",
"compose": {
"include": [ {
"system": "http://example.com/my_code_system",
"filter": [ {
"property": "concept",
"op": "is-a",
"value": "A"
} ]
}, {
"system": "http://example.com/my_code_system",
"concept": [ {
"code": "A"
} ]
} ]
},
"expansion": {
"identifier": "442d78a4-1fb5-452e-8df6-94802129a653",
"timestamp": "2021-04-06T14:38:39-04:00",
"total": 4,
"offset": 0,
"parameter": [ {
"name": "offset",
"valueInteger": 0
}, {
"name": "count",
"valueInteger": 1000
} ],
"contains": [ {
"system": "http://example.com/my_code_system",
"code": "A",
"display": "Code A",
"contains": [ {
"system": "http://example.com/my_code_system",
"code": "AB",
"display": "Code AB"
}, {
"system": "http://example.com/my_code_system",
"code": "AA",
"display": "Code AA",
"contains": [ {
"system": "http://example.com/my_code_system",
"code": "AAA",
"display": "Code AAA"
} ]
} ]
} ]
}
}
When building applications that capture data using coded values, a common requirement is to search for codes. This might be done in order to present a user with a dropdown-list, or to provide a type-ahead display with codes matching the characters that a user has entered so far in a text box.
The standard mechanism for performing searches is to use the ValueSet $expand operation. A simple example is shown below, searching for all codes in the http://acme.org
CodeSystem (i.e. the CodeSystem in the repository where CodeSystem.url = http://acme.org) having a display name starting with the string "Systolic".
POST /ValueSet/$expand
Content-Type: application/fhir+json
{
"resourceType": "ValueSet",
"compose": {
"include": [ {
"system": "http://acme.org",
"filter": [ {
"property": "display",
"op": "=",
"value": "Systolic"
} ]
} ]
}
}