Constraint

Constraint is a component of the FHIR Schema that specifies FHIRPath constraints.

Syntax

Constraint ID property:

  • <your-constraint-id> (string)

    Expression property:

    • expression (string)

    Human property:

    • human (string)

    Severity property:

    • severity (string: error | warning | guideline)

Constraint ID

A constraint ID must be unique within the constraints declaration scope. It serves as an identifier for the constraint, aiding in error identification by logging which constraint was violated.

Expression

A FHIRPath expression. For technical details, please refer to the ANSI FHIRPath specification.

Examples

Example of a constraint on the contact attribute in the FHIR R4 Patient schema:

id: Patient
url: http://hl7.org/fhir/StructureDefinition/Patient
package-meta:
  name: hl7.fhir.r4.core
  version: 4.0.1
  path: "/tmp/lw-fhir-schema-repository/hl7.fhir.r4.core#4.0.1"
base: http://hl7.org/fhir/StructureDefinition/DomainResource
kind: resource
type: Patient
derivation: specialization
elements:
  deceasedBoolean:
    scalar: true
    summary: true
    modifier: true
    type: boolean
    choiceOf: deceased
  maritalStatus:
    binding:
      valueSet: http://hl7.org/fhir/ValueSet/marital-status
      strength: extensible
    scalar: true
    type: CodeableConcept
  deceasedDateTime:
    scalar: true
    summary: true
    modifier: true
    type: dateTime
    choiceOf: deceased
  managingOrganization:
    refers:
    - http://hl7.org/fhir/StructureDefinition/Organization
    scalar: true
    summary: true
    type: Reference
 gender:
    binding:
      valueSet: http://hl7.org/fhir/ValueSet/administrative-gender
      strength: required
      codesystems:
      - http://hl7.org/fhir/administrative-gender
   type: code
   scalar: true
    summary: true
  multipleBirth:
    choices:
    - multipleBirthBoolean
    - multipleBirthInteger
    scalar: true
 name:
    summary: true
   type: HumanName
   array: true
  address:
    summary: true
    type: Address
    array: true
  identifier:
    summary: true
    type: Identifier
    array: true
  photo:
    type: Attachment
    array: true
  link:
    summary: true
    modifier: true
    required:
    - other
    - type
    type: BackboneElement
    array: true
    elements:
      other:
        refers:
        - http://hl7.org/fhir/StructureDefinition/Patient
        - http://hl7.org/fhir/StructureDefinition/RelatedPerson
        scalar: true
        summary: true
        type: Reference
      type:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/link-type
          strength: required
          codesystems:
          - http://hl7.org/fhir/link-type
        scalar: true
        summary: true
        type: code
  birthDate:
    scalar: true
    summary: true
    type: date
  multipleBirthBoolean:
    scalar: true
    type: boolean
    choiceOf: multipleBirth
  communication:
    required:
    - language
    type: BackboneElement
    array: true
    elements:
      language:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/languages
          strength: preferred
        scalar: true
        type: CodeableConcept
      preferred:
        scalar: true
        type: boolean
  telecom:
    summary: true
    type: ContactPoint
    array: true
  active:
    scalar: true
    summary: true
    modifier: true
    type: boolean
  deceased:
    choices:
    - deceasedBoolean
    - deceasedDateTime
    scalar: true
  generalPractitioner:
    refers:
    - http://hl7.org/fhir/StructureDefinition/Organization
    - http://hl7.org/fhir/StructureDefinition/Practitioner
    - http://hl7.org/fhir/StructureDefinition/PractitionerRole
    type: Reference
    array: true
  contact:
    constraints:
      pat-1:
        human: SHALL at least contain a contact's details or a reference to an organization
        severity: error
        expression: name.exists() or telecom.exists() or address.exists() or organization.exists()
    type: BackboneElement
    array: true
    elements:
      relationship:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/patient-contactrelationship
          strength: extensible
        type: CodeableConcept
        array: true
      name:
        scalar: true
        type: HumanName
      telecom:
        type: ContactPoint
        array: true
      address:
        scalar: true
        type: Address
      gender:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/administrative-gender
          strength: required
          codesystems:
          - http://hl7.org/fhir/administrative-gender
        scalar: true
        type: code
      organization:
        refers:
        - http://hl7.org/fhir/StructureDefinition/Organization
        scalar: true
        type: Reference
      period:
        scalar: true
        type: Period
  multipleBirthInteger:
    scalar: true
    type: integer
    choiceOf: multipleBirth

Data sample adhering to the previously mentioned schema:

resourceType: Patient
contact:
  - gender: true
    name:
      - given:
          - John
        family: Smith

Data sample not conforming to the previously mentioned schema:

resourceType: Patient
contact:
  - gender: true

Variables in Expressions

The ANSI FHIRPath specification defines two environment variables for the FHIRPath engine's evaluation context:

  • %ucum — URL for UCUM (http://unitsofmeasure.org), as per HL7 UCUM.
  • %context — The node evaluated by the engine at the start of evaluation.

FHIR extends FHIRPath with two additional variables:

  • %rootResource — the container resource for %resource
  • %resource — the resource containing the node in %context

%ucum

Holds the URL http://unitsofmeasure.org for UCUM.

%context

%context varies based on where the constraints property is defined:

Constraints at Specific Elements

For constraints in the contact element of the FHIR R4 Patient schema:

id: Patient
url: http://hl7.org/fhir/StructureDefinition/Patient
package-meta:
  name: hl7.fhir.r4.core
  version: 4.0.1
  path: "/tmp/lw-fhir-schema-repository/hl7.fhir.r4.core#4.0.1"
base: http://hl7.org/fhir/StructureDefinition/DomainResource
kind: resource
type: Patient
derivation: specialization
elements:
  deceasedBoolean:
    scalar: true
    summary: true
    modifier: true
    type: boolean
    choiceOf: deceased
  maritalStatus:
    binding:
      valueSet: http://hl7.org/fhir/ValueSet/marital-status
      strength: extensible
    scalar: true
    type: CodeableConcept
  deceasedDateTime:
    scalar: true
    summary: true
    modifier: true
    type: dateTime
    choiceOf: deceased
  managingOrganization:
    refers:
    - http://hl7.org/fhir/StructureDefinition/Organization
    scalar: true
    summary: true
    type: Reference
 gender:
    binding:
      valueSet: http://hl7.org/fhir/ValueSet/administrative-gender
      strength: required
      codesystems:
      - http://hl7.org/fhir/administrative-gender
   type: code
   scalar: true
    summary: true
  multipleBirth:
    choices:
    - multipleBirthBoolean
    - multipleBirthInteger
    scalar: true
 name:
    summary: true
   type: HumanName
   array: true
  address:
    summary: true
    type: Address
    array: true
  identifier:
    summary: true
    type: Identifier
    array: true
  photo:
    type: Attachment
    array: true
  link:
    summary: true
    modifier: true
    required:
    - other
    - type
    type: BackboneElement
    array: true
    elements:
      other:
        refers:
        - http://hl7.org/fhir/StructureDefinition/Patient
        - http://hl7.org/fhir/StructureDefinition/RelatedPerson
        scalar: true
        summary: true
        type: Reference
      type:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/link-type
          strength: required
          codesystems:
          - http://hl7.org/fhir/link-type
        scalar: true
        summary: true
        type: code
  birthDate:
    scalar: true
    summary: true
    type: date
  multipleBirthBoolean:
    scalar: true
    type: boolean
    choiceOf: multipleBirth
  communication:
    required:
    - language
    type: BackboneElement
    array: true
    elements:
      language:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/languages
          strength: preferred
        scalar: true
        type: CodeableConcept
      preferred:
        scalar: true
        type: boolean
  telecom:
    summary: true
    type: ContactPoint
    array: true
  active:
    scalar: true
    summary: true
    modifier: true
    type: boolean
  deceased:
    choices:
    - deceasedBoolean
    - deceasedDateTime
    scalar: true
  generalPractitioner:
    refers:
    - http://hl7.org/fhir/StructureDefinition/Organization
    - http://hl7.org/fhir/StructureDefinition/Practitioner
    - http://hl7.org/fhir/StructureDefinition/PractitionerRole
    type: Reference
    array: true
  contact:
    constraints:
      pat-1:
        human: SHALL at least contain a contact's details or a reference to an organization
        severity: error
        expression: name.exists() or telecom.exists() or address.exists() or organization.exists()
    type: BackboneElement
    array: true
    elements:
      relationship:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/patient-contactrelationship
          strength: extensible
        type: CodeableConcept
        array: true
      name:
        scalar: true
        type: HumanName
      telecom:
        type: ContactPoint
        array: true
      address:
        scalar: true
        type: Address
      gender:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/administrative-gender
          strength: required
          codesystems:
          - http://hl7.org/fhir/administrative-gender
        scalar: true
        type: code
      organization:
        refers:
        - http://hl7.org/fhir/StructureDefinition/Organization
        scalar: true
        type: Reference
      period:
        scalar: true
        type: Period
  multipleBirthInteger:
    scalar: true
    type: integer
    choiceOf: multipleBirth

With this data sample:

resourceType: Patient
active: true
gender: male
contact:
  - gender: true
    name:
      - given:
          - John
        family: Smith

The FHIRPath engine processes this data node:

- gender: true
  name:
    - given:
        - John
      family: Smith

Constraints at Top Level

For top-level constraints in the US Core 5.0.1 Patient schema:

url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient
constraints:
  us-core-6:
    human: Either Patient.name.given and/or Patient.name.family SHALL be present or
      a Data Absent Reason Extension SHALL be present.
    severity: error
    expression: "(name.family.exists() or name.given.exists()) xor extension.where(url='http://hl7.org/fhir/StructureDefinition/data-absent-reason').exists()"
package-meta:
  name: hl7.fhir.us.core
  version: 5.0.1
  path: "/tmp/lw-fhir-schema-repository/hl7.fhir.us.core#5.0.1"
id: us-core-patient
base: http://hl7.org/fhir/StructureDefinition/Patient
kind: resource
required:
- identifier
- name
- gender
type: Patient
elements:
  extension:
    slicing:
      slices:
        race:
          schema:
            type: Extension
          min: 0
          max: 1
          match:
            type: pattern
            value:
              url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-race
        ethnicity:
          schema:
            type: Extension
          min: 0
          max: 1
          match:
            type: pattern
            value:
              url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity
        birthsex:
          schema:
            type: Extension
          min: 0
          max: 1
          match:
            type: pattern
            value:
              url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex
        genderIdentity:
          schema:
            type: Extension
          min: 0
          max: 1
          match:
            type: pattern
            value:
              url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-genderIdentity
      discriminator:
      - type: value
        path: url
      rules: open
  identifier:
    mustSupport: true
    required:
    - system
    - value
    elements:
      system:
        mustSupport: true
      value:
        mustSupport: true
  name:
    mustSupport: true
    elements:
      family:
        mustSupport: true
      given:
        mustSupport: true
  telecom:
    required:
    - system
    - value
    elements:
      system:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/contact-point-system
          strength: required
        mustSupport: true
      value:
        mustSupport: true
      use:
        binding:
          valueSet: http://hl7.org/fhir/ValueSet/contact-point-use
          strength: required
        mustSupport: true
  gender:
    binding:
      valueSet: http://hl7.org/fhir/ValueSet/administrative-gender
      strength: required
      codesystems:
    mustSupport: true
    type: code
  birthDate:
    mustSupport: true
  address:
    mustSupport: true
    elements:
      line:
        mustSupport: true
      city:
        mustSupport: true
      state:
        binding:
          valueSet: http://hl7.org/fhir/us/core/ValueSet/us-core-usps-state
          strength: extensible
        mustSupport: true
      postalCode:
        mustSupport: true
      period:
        mustSupport: true
  communication:
    elements:
      language:
        binding:
          valueSet: http://hl7.org/fhir/us/core/ValueSet/simple-language
          strength: extensible
        mustSupport: true
derivation: constraint

With this data sample:

resourceType: Patient
active: true
gender: male
name:
  - given:
    - John
    family: Smith

The engine processes the entire resource as the data node:

resourceType: Patient
active: true
gender: male
name:
  - given:
    - John
    family: Smith

%resource & %rootResource

These variables are similar to %context and vary based on schema location:

Consider this schema:

url: "contained-invariant-profile"
base: "Patient"
elements:
  contained:
    constraints:
      cont-1:
        human: "Check context variables are set correctly"
        severity: "error"
        expression: "%context.type().name.trace('cont-1-context:') = 'Practitioner'
                     and %resource.type().name.trace('cont-1-resource') = 'Patient'
                     and %rootResource.type().name.trace('cont-1-root') = 'Patient'"
    type: "Practitioner"
    elements:
      name:
        constraints:
          cont-2:
            human: "Check context variables are set correctly"
            severity: "error"
            expression: "%context.type().name.trace('cont-2-context:') = 'HumanName'
                         and %resource.type().name.trace('cont-2-resource') = 'Practitioner'
                         and %rootResource.type().name.trace('cont-2-rootResource') = 'Patient'"
  generalPractitioner:
    constraints:
      cont-3:
        human: "Check context variables are set correctly"
        severity: "error"
        expression: "%context.type().name.trace('cont-3-context') = 'Reference'
                     and %resource.type().name.trace('cont-3-resource') = 'Patient'
                     and %rootResource.type().name.trace('cont-3-rootresource') = 'Patient'"

Testing against this data sample:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

cont-1 at elements.contained.constraints

Variables for cont-1:

%context:

- resourceType: Practitioner
  name:
    - family: a

%rootResource:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

%resource:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

cont-2 at elements.contained.name.constraints

Variables for cont-2:

%context:

- family: a

%rootResource:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

%resource:

resourceType: Practitioner
name:
 - family: a

cont-3 at elements.generalPractitioner.constraints

Variables for cont-3:

%context:

- reference: Practitioner/1

%rootResource:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

%resource:

resourceType: Patient
meta:
  profile:
  - contained-invariant-profile
contained:
- resourceType: Practitioner
  name:
  - family: a
generalPractitioner:
- reference: Practitioner/1

Human

This is a textual description of your constraint. While not mandatory, it is typically beneficial to include at least a brief explanation of your constraint.

Severity

Types of constraint severity:

  • error: Failing results in a validation error.
  • warning
  • guideline