Skip to content

Instantly share code, notes, and snippets.

@lawley
Last active March 20, 2025 23:04
Show Gist options
  • Save lawley/2b3b407b9998a1b537bb25f6302c1e38 to your computer and use it in GitHub Desktop.
Save lawley/2b3b407b9998a1b537bb25f6302c1e38 to your computer and use it in GitHub Desktop.
WiP proposal for parameterised ValueSets

Parameterised ValueSets V0.2

Background and Motivation

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.

Description

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 ValueSet definition

Parameterised ValueSets are defined in the same way as regular ValueSets, except that:

  1. the parameterDefinition extension is used to define and document the parameter names, and
  2. the value field of the ValueSet.compose.include.filter[i] is left empty, and the cqf-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"
            }
          }]
        }
      }],
    }]
  }
}

Notes:

  • 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.

Parameterised ValueSet expansion

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.

Notes:

  • While it is possible to define arbitrary parameter names, care should be taken to avoid naming conflicts with existing parameters to ValueSet/$expand and ValueSet/$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.

Use in Questionnaires

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"
@brianpos
Copy link

Here's a sample of what the questionnaire item could look like to be able to invoke the content:

                    "linkId": "language_vsc.3",
                    "text": "language (valueset canonical - no version)",
                    "type": "choice",
                    "_answerValueSet":{
                        "extension": [
                            {
                                "url": "....AdditionalParameters",
                                "extension": [
                                    {
                                        "name":"propertyA",
                                        "valueExpression": {
                                            "expression":"item(12).answer.valueString.join(',')"
                                            
                                        }
                                    },
                                    {
                                        "name":"activeOnly",
                                        "valueBoolean": true
                                    },
                                    {
                                        "name":"useSupplement",
                                        "valueCanonical": "...supplimentCanonical"
                                    },
                                    {
                                        "name":"property",
                                        "valueString": "country-code"
                                    }
                                ]
                            }
                            ]
                    },
                    "answerValueSet": "http://hl7.org/fhir/ValueSet/languages"

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment