Frequently asked questions

  1. Is it possible to slice a value[X] by data type?
  2. How do you decide between slicing and creating a new Profile?
  3. How to slice a CodeableConcept 0..* element to support multiple slices bound to different ValueSets from a single CodeSystem hierarchy?
  4. What’s the difference between setting the minimum cardinality to 1 and using MustSupport?
  5. How should I use the MustSupport element when minimum cardinality is already more than 0?
  6. Should I constrain the maximum cardinality of elements that I don’t use to 0?
  7. When can I consider using the Basic resource?
  8. How should I deal with versioning of my profiles?
  9. How can I slice by target profile of a reference?
  10. Are you allowed to constrain profiled data types within a derived profile?
  11. When should you use the Person resource and why does it contain “duplicate” elements (e.g. address)?
  12. Can you use the link element to link Patients to more than one RelatedPerson? What if a RelatedPerson is related to more than 1 patient? For example, two patients with the same mother.

Is it possible to slice a value[x] by data type?

Choice elements can be sliced by data type. In this case, a discriminator needs to be added with type=type and path=$this.

How do you decide between slicing and creating a new Profile?

There’s an interesting discussion on this topic on the Zulip channel. Of course it depends on your use case, but say for example that you have multiple types of Observations that you want to profile (e.g. heartrate, blood pressure and BMI). You can follow two strategies:

  1. Create a “master” Observation profile, which contains all constraints that are generic to all your Observations, and create derived profiles based on your master profile for each type of Observation.
  2. Create one Observation profile and add slices for each type of Observation.

Both strategies are valid. Although the first one creates more maintenance, it can be useful in cases where you have many Observation type specific constraints and you want to be able to re-use these constraints. When this is not the case, the second strategy might be a better option to consider.

How to slice a CodeableConcept 0..* element to support multiple slices bound to different ValueSets from a single CodeSystem hierarchy?

Just slice on the element (code) that has the binding and declare the value set for each. So long as the value sets are mutually exclusive (or at least all the codes you receive only exist in one of the value sets), validation should work.

What’s the difference between setting the minimum cardinality to 1 and using MustSupport?

When the minimum cardinality of an element is set to 1, this means that the element is mandatory. An instance will fail validation if the element is not present when its minimum cardinality is 1. When an element is labeled with the MustSupport flag, implementations are required to provide support for the element. This means that a system doesn’t necessarily need to send it, but for example should be capable of sending, capturing and/or storing it. The meaning of support depends on its context and can be different for different use cases. For this reason, the meaning of MustSupport should be clarified in the Implementation Guide.

How should I use the MustSupport element when minimum cardinality is already more than 0?

As explained above there is a subtle difference between setting the minimum cardinality and using the MustSupport flag. A minimum cardinality > 0 means that senders are required to include the element, while the MustSupport flag says something about the system requirements to support it (e.g. store or send it). It is not necessary to flag elements with minimum cardinality > 0 with MustSupport, but the meaning of not setting the MustSupport flag to true would be that senders are allowed to send a fixed value and receivers are allowed to ignore the element.

Should I constrain the maximum cardinality of elements that I don’t use to 0?

Although it depends on the use case, we believe that it is good practice to try to avoid setting the maximum cardinality of elements to 0. First, you can freely ignore elements that you don’t use, so there is no specific need to constrain cardinality unless you want to explicitly forbid the use of the element. Second, your profile will be more reusable (and easier to implement) if you just choose to ignore non-relevant elements instead of constraining them. Especially when you create profiles on a higher (e.g. national) level, which serve as a base to derive use-case specific profiles from, it is a good idea to use open models that are generic and reusable. A good alternative to distinguish relevant from non-relevant elements is to use the MustSupport flag in elements that are relevant for your use case.

When can I consider using the Basic resource?

Before considering to use the Basic resource, always make absolutely sure that there is no existing resource that meets your requirements. The Basis resource should only be used when you need a resource that clearly doesn’t fit in one of the core Resources. Note that in most cases your custom resource will not end up in the FHIR specification eventually as FHIR can’t incorporate all use case specific requirements if we want to keep it generic and maintainable. Examples of scenarios in which you could consider using the Basis resource are:

  1. If you need a resource concept that does not exist yet, but will likely be defined in the future
  2. If you need a narrative-only construct that doesn’t correspond to one of the existing resources
  3. You want to capture information that should be in a standard resource, but you want to use a custom format that is not aligned with the official resource. Note that this is not FHIR conformant as it prevents healthcare data from being safely processed by other conformant systems.

When using the Basic resource, make sure you follow the best practices to make sure that there is no existing resource that meets your requirements and your resource can be considered for inclusion in the official specification.

How should I deal with versioning of my profiles?

This is still an important topic of discussion within the FHIR community and a common problem that profile authors face. Profiles often contain constrained references to other profiles used in the same use case (for example hospital X has profiled the Patient resource and wants to constrain all references to Patient in their other profiles to their specific Patient profile). This means that if a breaking change in the Patient profile leads to a new version, all references to this profile need to be updated and all updated profiles need to be (re)published at once as a batch. Although there is no definite decision yet, we believe the solution should go towards some kind of packaging. Our colleague, Ewout, wrote an interesting blog on this topic. The discussion continues on Zulip.

How can I slice by target profile of a reference?

To slice a Reference element by target profile you would need a discriminator with Type=Profile and Path=item.reference.resolve()

Example:

<element id="DiagnosticReport.result">
      <path value="DiagnosticReport.result"/> 
      <slicing> 
        <discriminator> 
          <type value="profile"/> 
          <path value="item.reference.resolve()"/> 
        </discriminator> 
        <ordered value="true"/> 
        <rules value="closed"/> 
      </slicing> 

Are you allowed to constrain profiled data types within a derived profile?

It is indeed possible to add constraints to a profiled data type within a derived profile. For example, let’s say you want to create a derived profile on nl-core-patient (the Dutch national Patient profile). This profile uses the nl-core-humanname profile on humanname. If you want to add your own constraints to nl-core-humanname, it is not necessary to create a derived profile on nl-core-humanname. You can directly add the constraints in your derived nl-core-patient profile.

When should you use the Person resource and why does it contain “duplicate” elements (e.g. address)?

Although it is a logical thought, Person is not a super class of Patient or Practitioner. The Person resource is meant to link resources that are about the same person. For example, a Practitioner can also be a Patient. This relationship can be expressed by using the link element in the Person resource. Each individual resource in FHIR contains just the amount of information that is needed for that concept. That’s why both Person and Patient have addresses. It wouldn’t make sense to collect just an ‘address’ resource, because it doesn’t have any meaning without the context of, for example, a Person.

The link element can’t be used for this purpose as it is explicitly used to link resources that are about the same person. The relationship to a Patient is captured in the RelatedPerson, in the patient element. The cardinality of this element is 1..1 meaning that a RelatedPerson resource is always linked to exactly 1 Patient resource. If you need to define more than one relationship, this would require multiple instances or the use of extensions. The Person resource could link these instances together to express that they are about the same person.