A common activity in a data entry scenarion like a Questionnaire is to have the set of available options for one question depend on an answer to another question. For example, after choosing a country, the set of available options for a question about a state or region would depend on the chosen country. Ideally a ValueSet would be bound to the state/region question, but since it needs to be pre-defined we cannot have one that is sensitive to the country.
Similar examples exist when questions correlating diagnoses or procedures and body sites/regions, or medications, or tests.
Ontoserver introduces support for parameterised ValueSets that consists of two parts.
The first part consists of how you define a parameterised ValueSet, while the second part consists of how you expand a parameterised ValueSet.
Parameterised ValueSets are defined in the same way as regular ValueSets, except that:
- the
parameterDefinition
extension is used to define and document the parameter names, and - the
value
field of theValueSet.compose.include.filter[i]
is left empty, and thecqf-expression
is used to supply its value.
{
"resourceType": "ValueSet",
"extension" : [{
"url": ".../parameterDefinition",
"extension" : [{
"url": "name",
"valueCode" : "p-inactive",
}, {
"url": "documentation",
"valueString" : "whether the record is inactive or not"
}]
}],
"url": "http://example.com/ValueSet/parameterised",
"compose": {
"include": [{
"valueSet": [ "http://snomed.info/sct?fhir_vs=refset/929360041000036105" ],
"system": "http://snomed.info/sct",
"filter": [{
"property": "inactive",
"op": "=",
"_value": {
"extension" :[{
"url" : ".../StructureDefinition-cqf-expression",
"valueExpression" : {
"expression" : "%p-inactive"
}
}]
}
}],
}]
}
}
- Separation of "definition" and "use" enables the parameter to be used more than once in different parts of the
ValueSet.compose
and provides a place to document the parameter. - Using
cqf-expression
rather than just naming the parameter allows for additional logic to be applied to the parameter value. For example, the parameter value might be one of "left" or "right", and then it can be mapped to the corresponding SNOMED CT code in one filter and the corresponding LOINC code in another filter.
Having defined a parameterised ValueSet, you can expand it by providing the values for the parameters as query parameters in a GET request or in as Parameters.parameter
elements in a POST request.
The following GET request:
/ValueSet/$expand?url=http://example.com/ValueSet/parameterised&p-inactive=true
will result in the expansion of a ValueSet defined as follows:
{
"resourceType": "ValueSet",
"url": "http://example.com/ValueSet/parameterised",
"compose": {
"include": [{
"valueSet": [ "http://snomed.info/sct?fhir_vs=refset/929360041000036105" ],
"system": "http://snomed.info/sct",
"filter": [{
"property": "inactive",
"op": "=",
"value": "true"
}],
}]
}
}
All parameters that are used in the expansion MUST be included in the ValueSet.expansion.parameters
element of the resulting ValueSet.
If the cqf-expression evaluates to ()
, then corresponding filter element is omitted from the compose definition used for expansion.
Hence the following GET request:
/ValueSet/$expand?url=http://example.com/ValueSet/parameterised
will result in the expansion of a ValueSet defined as follows:
{
"resourceType": "ValueSet",
"url": "http://example.com/ValueSet/parameterised",
"compose": {
"include": [{
"valueSet": [ "http://snomed.info/sct?fhir_vs=refset/929360041000036105" ],
"system": "http://snomed.info/sct",
}]
}
}
It is the terminology server's discretion to decide whether the parameterised ValiueSet.compose or the computed ValueSet.compose is used in the response when for includeDefinition=true
.
- While it is possible to define arbitrary parameter names, care should be taken to avoid naming conflicts with existing parameters to
ValueSet/$expand
andValueSet/$validate-code
. - It is recommended to use a prefix such as
p-
for parameter names to avoid naming conflicts. This could also assist when defining API Gateway rules that only allow whitelisted query parameters.
A primary use context for parameterised ValueSets is in Questionnaires.
The additionalParameters
extension has been proposed (thanks @brianpos) and would allow specifying the parameter values to be used for the expansion of a parameterised ValueSet.
"linkId": "language_vsc.3",
"text": "language (valueset canonical - no version)",
"type": "choice",
"_answerValueSet":{
"extension": [{
"url": "....AdditionalParameters",
"extension": [{
"name":"p-propertyA",
"valueExpression": {
"expression":"item(12).answer.valueString.join(',')"
}
}, {
"name":"activeOnly",
"valueBoolean": true
}, {
"name":"useSupplement",
"valueCanonical": "...supplimentCanonical"
}, {
"name":"p-property",
"valueString": "country-code"
}]
}]
},
"answerValueSet": "http://hl7.org/fhir/ValueSet/languages"
Here's a sample of what the questionnaire item could look like to be able to invoke the content:
So the complex extension on the answerValueset now includes the additional parameters that are to be passed to the $filter operation.
https://build.fhir.org/valueset-operation-expand.html.
In this casse we sent the activeOnly and useSuppliment flags to the calls, along with the propertyA if a result was returned from the expression.
The naming of this propertyA thing is where the other discussions are kicking in - I don't have a specifically strong opinion on that, but I love how clean this is for the questionnaire definition.