Skip to content

Designing code filters in ValueSets

Ewout Kramer edited this page Feb 28, 2024 · 4 revisions

Looking at a ValueSet with a filter from V3 (https://terminology.hl7.org/5.4.0/ValueSet-v3-ActClassClinicalDocument.json.html) we find the following relevant part:

  "compose" : {
    "include" : [
      {
        "system" : "http://terminology.hl7.org/CodeSystem/v3-ActClass",
        "filter" : [
          {
            "property" : "concept",
            "op" : "is-a",
            "value" : "DOCCLIN"
          }
        ]
      }
    ]
  }

The is-a part is defined in the spec, but the property could change per codesystem. In this case it is concept. So which codes are a DOCCLIN? Now, looking at CodeSystem we see:

image

It seems the natural way to express an is-a relationship is via the nested concept element within concept. It even says that is expresses an "is-a" relationship. Now, if we take an actual look at the CodeSystem we see:

   {
      "code" : "CDALVLONE",
      "display" : "CDA Level One clinical document",
      "definition" : "A clinical document that conforms to Level One of the HL7 Clinical Document Architecture (CDA)",
      "property" : [
        {
          "code" : "status",
          "valueCode" : "active"
        },
        {
          "code" : "internalId",
          "valueCode" : "14795"
        },
        {
          "code" : "Name:Class",
          "valueCode" : "CDALevelOneClinicalDocument"
        },
        {
          "code" : "subsumedBy",
          "valueCode" : "DOCCLIN"
        },
        {
          "code" : "Name:Participation:act:Act",
          "valueString" : "&"
        }
      ]
    },

In this codesystems, all codes are in an flat list, and the property subsumedBy expresses the "is-a" relationship - so it is not using the nested codes. The disadvantage of this approach is that you'd have to scan the codes multiple times to find codes that are more than one step away from the code in the filter.

However, in another v3 Codesystem, https://terminology.hl7.org/5.4.0/CodeSystem-v3-ActMood.json.html, this is expressed hierarchically:

 {
      "code" : "_ActMoodPredicate",
      "display" : "ActMoodPredicate",
      "definition" : "**Definition:** An act that expresses condition statements for other acts.",
      "property" : [
        {
          "code" : "notSelectable",
          "valueBoolean" : true
        },
        {
          "code" : "status",
          "valueCode" : "active"
        },
        {
          "code" : "internalId",
          "valueCode" : "20936"
        },
        {
          "code" : "Name:Class",
          "valueCode" : "Predicate"
        }
      ],
      "concept" : [
        {
          "code" : "CRT",

Note the "notSelectable" and "status" here, this could influence validation. We should copy the properties over to the valueset, just in case we need them (when we build specific logic to understand these properties).

This CodeSystem formally introduces this relationship in its header, just like the properties mentioned above:

"hierarchyMeaning" : "is-a",
  "content" : "complete",
  "property" : [
    {
      // Stuff left out
      "code" : "Specializes",
      "type" : "Coding"
    },
    {
      "code" : "Generalizes",
      "description" : "Inverse of Specializes.  Only included as a derived relationship.",
      "type" : "Coding"
    },
    {
      "code" : "internalId",
      "uri" : "http://terminology.hl7.org/CodeSystem/utg-concept-properties#v3-internal-id",
      "description" : "The internal identifier for the concept in the HL7 Access database repository.",
      "type" : "code"
    },
    // etcetera

See also https://simplifier.net/fql/8db92a0842bf626 for a list of filters found in the R4 core spec.

Clone this wiki locally