Ceci est le deuxième article de la série Introduction à la terminologie FHIR. Nous passerons en revue les concepts fondamentaux qui composent le module de Terminology FHIR. Nous verrons des exemples concrets des problèmes qu'il peut résoudre, et nous donnerons un aperçu de la façon dont les différentes pièces s'assemblent.
Cas d'utilisation
Comme nous l'avons mentionné précédemment, nous avons observé que les nouveaux arrivants dans FHIR sous-utilisent les solutions de Terminology. Nous croyons que cela s'explique en partie par un manque de sensibilisation aux problèmes qu'elles peuvent résoudre — certaines personnes associent peut-être la Terminology à des sujets comme les normes, la conformité, la réglementation. Nous pensons donc qu'un bon point de départ est de présenter quelques cas d'utilisation concrets facilement mis en œuvre grâce à un serveur de terminologie. D'ailleurs, tous ces exemples s'exécutent en direct contre notre instance bac à sable.
Chaque onglet présente un exemple en direct, des champs de recherche et listes déroulantes au mappage et à la traduction ; ouvrez le tiroir au bas du cadre pour voir les requêtes et réponses réelles1.
Contexte
Lorsqu'un médecin écrit « crise cardiaque » et qu'un autre écrit « infarctus du myocarde », ils désignent la même chose. Mais pour un système logiciel, ou tout flux de travail à grande échelle, ce sont simplement deux chaînes de texte différentes. Pouvoir partager le sens entre les parties est primordial pour l'interopérabilité. C'est à cela que servent les terminologies médicales. L'un des premiers exemples de terminologie médicale est la Classification internationale des maladies (CIM), adoptée en 1893 pour codifier les causes de décès. Elle est antérieure aux logiciels et est encore utilisée aujourd'hui.
Nous travaillerons avec un ensemble de constructions qui relèvent de la définition d'une terminologie : taxonomies, ontologies, nomenclatures, ensembles de codes, vocabulaires, classifications. Pour des raisons pratiques, nous les appellerons terminologies et les définirons comme un ensemble de termes dotés d'un identifiant stable lisible par machine. Elles peuvent être infinies, avoir des synonymes, des propriétés, des relations, une structure, etc. Mais la caractéristique principale dont nous aurons besoin est que chaque élément possède un identifiant stable (code) et une étiquette textuelle (terme/affichage).
Dans le développement Web « ordinaire », les développeurs utilisent des terminologies en permanence (même si elles ne sont pas appelées ainsi). Elles sont fréquemment mises en œuvre sous forme d'énumérations ou de tables d'éléments avec une vue d'administration CRUD (il est très courant que les énumérations soient leurs propres codes et que les tables d'éléments utilisent l'identifiant de base de données comme identifiant). Les exemples ci-dessus auraient très bien pu être mis en œuvre à l'aide de ces patrons.
FHIR fournit un Module de Terminology conçu pour résoudre ces problèmes et d'autres. Un aspect intéressant est que les mêmes abstractions permettent d'exprimer aussi bien des ontologies normalisées, conformes et faisant autorité à grande échelle que des listes locales courtes de codes de type énumération.
Valeurs codées
De nombreuses ressources FHIR auront des champs dont le domaine de valeurs possibles est tiré d'une liste (une terminologie). Leurs valeurs sont des codes attribués ailleurs qui identifient un concept défini. Par exemple :
resourceType: Patient
name:
- given: [Jane]
family: Doe
gender: female
Remarquez que, dans ce cas, name est une propriété non liée : elle peut prendre n'importe quel nom humain, tandis que gender ne peut prendre que l'une des quatre valeurs suivantes : male, female, other, unknown. Dans ce cas, female est une valeur codée.
Une valeur codée est principalement une paire composée de « system » et de « code », où system est une URL2 qui identifie le système de codes (terminologie) qui définit les codes. Cette décision a des implications importantes sur la découvrabilité des valeurs codées : au lieu de trouver une chaîne dans la nature qui ressemble à un code LOINC, les valeurs codées sont accompagnées de l'identifiant de leur système de codes. Dans le cas de gender ci-dessus, le system est implicite (Administrative Gender, http://hl7.org/fhir/administrative-gender) — nous verrons bientôt pourquoi.
FHIR définit 3 types de données principaux pour représenter ces codes3 : code, Coding et CodeableConcept.
code: L'instance représente le code uniquement. Le system est implicite.Coding: Le type de données contient un code et un system qui identifie l'origine de la définition du code.CodeableConcept: Un type qui représente un concept par du texte libre et/ou un ou plusieurs élémentscoding.
La plupart des éléments codés dans FHIR utilisent CodeableConcept puisqu'il offre la plus grande flexibilité. Il permet plusieurs codages et autorise du texte libre pour transmettre, par exemple, ce qu'un saisisseur de données a réellement tapé, ou les cas où aucun code n'est disponible. Il facilite également la transition, puisqu'on peut inclure d'anciens et de nouveaux codes dans la même structure (voir l'exemple Observation ci-dessous).
Le type de données Coding est utilisé lorsque l'intention est de référencer un code spécifique, et non d'exprimer un concept de manière générale. L'utilisation de Coding est rare, car il est moins flexible que CodeableConcept et n'autorise ni texte libre ni traductions.
Le type de données code apparaît généralement dans des scénarios de type énumération. Ces éléments ont typiquement une force de liaison (binding strength) required, c'est-à-dire que ce code doit provenir de l'ensemble de valeurs spécifié et qu'il n'est pas nécessaire de transmettre un code alternatif. Ces éléments sont habituellement impliqués dans la logique métier, comme la distribution selon une valeur, la comparaison exacte, etc. Par exemple : le statut d'une ressource — le code client pourrait ignorer les ressources retired ou n'agir que sur les ressources active.
Liaison (Binding)
Dans les types de données précédents, les codes sont de type string ; la façon de restreindre l'ensemble des valeurs qu'ils peuvent prendre est via les liaisons. La spécification lie l'élément à un ensemble de valeurs (value set), ce qui signifie qu'il ne peut prendre que des valeurs de cette liste.
Les liaisons ont deux propriétés principales : valueSet et strength. valueSet définit quels codes sont valides pour cet élément. strength indique comment la liaison doit être interprétée : required, extensible, preferred, example.

Dans l'exemple ci-dessus, Patient.gender est lié à l'ensemble de valeurs Administrative Gender avec une force required ; par conséquent, gender ne peut être que : male, female, other, unknown. Et maritalStatus est lié à Marital Status Codes avec une force extensible, ce qui signifie que les codes doivent provenir de cet ensemble de valeurs, sauf si le code attendu n'y est pas couvert.
Exemples de valeurs codées
resourceType: Patient
name:
- given: [Jane]
family: Doe
gender: female # code / AdministrativeGender (implicit)
maritalStatus: # CodeableConcept
text: Married
coding:
- system: http://terminology.hl7.org/CodeSystem/v3-MaritalStatus
code: M
display: Married
resourceType: Location
name : South Wing Neuro OR 1
status: suspended # code / LocationStatus (implicit)
operationalStatus: # Coding
system: http://terminology.hl7.org/CodeSystem/v2-0116
code: H
display: Housekeeping
type: # CodeableConcept
coding:
- system: http://terminology.hl7.org/CodeSystem/v3-RoleCode
code: RNEU
display: Neuroradiology unit
form: # CodeableConcept without codings
text: Room
resourceType: Observation
status: final # code / ObservationStatus (implicit)
code: # CodeableConcept with local and standard codings
coding:
- system: http://acmelabs.org
code: 104177
display: "Blood culture"
- system: http://loinc.org
code: 600-7
display: Bacteria identified in Blood by Culture
valueCodeableConcept: # CodeableConcept
coding:
- system: http://snomed.info/sct
code: 3092008
display: Staphylococcus aureus
interpretation:
text: Positive
coding:
- system: http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code: POS
Ressources
Nous allons maintenant examiner brièvement les ressources FHIR impliquées dans le module de Terminology. En pratique, vous les créez rarement directement. Elles sont généralement maintenues ailleurs et chargées4 dans (ou depuis) un serveur de terminologie.
Le module de Terminology définit quatre ressources terminologiques principales : CodeSystem, ValueSet, ConceptMap et NamingSystem. Nous consacrerons un article à chacune d'elles. Pour l'instant, nous donnons un bref aperçu de CodeSystem et de ValueSet.
CodeSystem
CodeSystem est sans doute la ressource la plus importante dans la Terminology FHIR. Elle sert à décrire un système de codes, ses attributs et son contenu. Dans sa forme la plus courante, elle contient une liste de concepts, chacun avec son code, ses désignations et ses propriétés.
Exemples
resourceType: CodeSystem
url: http://hl7.org/fhir/administrative-gender
version: 5.0.0
content: complete
status: active
concept:
- code: male
display: Male
- code: female
display: Female
- code: other
display: Other
- code: unknown
display: Unknown
resourceType: CodeSystem
content: supplement
supplements: http://hl7.org/fhir/administrative-gender
concept:
- code: male
designation:
- language: es
value: Masculino
- code: female
designation:
- language: es
value: Femenino
- code: other
designation:
- language: es
value: Otro
- code: unknown
designation:
- language: es
value: Desconocido
resourceType: CodeSystem
url: http://www.nlm.nih.gov/research/umls/rxnorm
version: '03022026'
publisher: National Library of Medicine
content: complete
filter:
- code: concept
operator: [is-a, generalizes, descendent-of]
value: comma-separated list of concept codes for direct equality testing
- code: NDC
operator: [=,in, exists]
value: NDC code
property:
- {code: TTY, type: string}
- {code: NDC, type: string}
- {code: RXN_STRENGTH, type: string}
- {code: dose_form_of, type: code}
- {code: has_ingredient, type: code}
- {code: has_tradename, type: code}
# ...
concept:
- code: '5640'
display: ibuprofen
property:
- code: TTY
valueString: IN
- code: has_tradename
valueCode: '1100067'
- code: ingredient_of
valueCode: '1152223'
- code: part_of
valueCode: '821036'
# ...
# ...
resourceType: CodeSystem
url: http://hl7.org/fhir/sid/icd-10-cm
version: '2025'
content: complete
property:
- description: Indicator [...] transactions ("billable code")
type: integer
code: valid
filter:
- description: Identify valid billable codes.
value: 0 = "header" – not valid [...]
code: valid
operator: ["="]
valueSet: http://hl7.org/fhir/sid/icd-10-cm/vs
concept:
- code: Chapter-1
display: Certain infectious and parasitic diseases (A00-B99)
concept:
- code: Section-A00-A09
display: Intestinal infectious diseases (A00-A09)
concept:
- code: A00
display: Cholera
concept:
- code: A00.0
display: Cholera due to Vibrio cholerae 01, biovar cholerae
property:
- code: valid
valueInteger: 1
# ...
ValueSet
Une ressource ValueSet spécifie un ensemble de codes tirés d'un ou de plusieurs systèmes de codes.
D'après notre expérience, il s'agit de l'une des ressources les plus mal comprises dans la Terminology FHIR. Une raison possible est que la différence entre les systèmes de codes et les ensembles de valeurs n'est pas toujours claire pour les développeurs. Le fait que, dans le noyau FHIR, la plupart des ressources CodeSystem aient un ValueSet équivalent incluant tous leurs codes n'aide pas à la clarté. Par exemple : http://hl7.org/fhir/administrative-gender et http://hl7.org/fhir/ValueSet/administrative-gender.
La distinction principale est que les systèmes de codes contiennent la définition des concepts, leur origine, tandis que les ensembles de valeurs sélectionnent des codes dans les systèmes de codes. Ainsi, un ensemble de valeurs peut contenir un sous-ensemble d'un système de codes, ou même en combiner plusieurs.
Par exemple, RxNorm est une terminologie des médicaments qui inclut des concepts pour les noms de marque, les ingrédients, les formes pharmaceutiques, etc. Nous pouvons définir un ensemble de valeurs des ingrédients dans RxNorm. Les concepts inclus resteraient des concepts RxNorm, mais nous n'aurions que les ingrédients.
Un autre cas d'utilisation courant pour les ensembles de valeurs est l'ajout d'une option nulle. Supposons que nous utilisions ISO 3166 (codes pays) dans un formulaire. Il affiche correctement tous les pays et leurs codes, mais il n'y a pas de code de pays « Inconnu ». Nous pouvons définir un ensemble de valeurs qui inclut tous les codes d'ISO 3166 et le concept UNK de NullFlavor.
Exemples
resourceType: ValueSet
url: http://example.org/rxnorm-ingredients
title: RxNorm Ingredients
compose:
include:
- system: http://www.nlm.nih.gov/research/umls/rxnorm
filter:
- property: TTY
op: =
value: IN
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/example
title: LOINC Codes for Cholesterol in Serum/Plasma
compose:
include:
- system: http://loinc.org
concept:
- code: 14647-2
display: Cholesterol [Moles/Volume]
- code: 2093-3
display: Cholesterol [Mass/Volume]
- code: 35200-5
display: Cholesterol [Mass Or Moles/Volume]
- code: 9342-7
display: Cholesterol [Percentile]
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/administrative-gender
status: active
compose:
include:
- system: http://hl7.org/fhir/administrative-gender
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/yesnodontknow
name: YesNoDontKnow
compose:
include:
- valueSet: ["http://terminology.hl7.org/ValueSet/v2-0136"]
- system: http://terminology.hl7.org/CodeSystem/data-absent-reason
concept:
- code: asked-unknown
display: Don't know
Opérations
La principale façon d'interagir avec le module de Terminology et ses ressources se fait par l'intermédiaire d'opérations. La spécification R6 définit 8 opérations spécifiques à la terminologie. Tout au long de cette série, nous examinerons la plupart d'entre elles en détail. Dans cet article, nous présentons $expand, celle qui alimente la plupart de nos exemples ci-dessus.
ValueSet/$expand
Étant donné un ensemble de valeurs, cette opération retourne la liste des codes qu'il définit. Elle est idéale pour alimenter des éléments d'interface : listes déroulantes, champs de recherche, sélecteurs de codes, etc. En plus de l'ensemble de valeurs, vous pouvez spécifier un filtre de recherche textuelle, la pagination, les propriétés et désignations à retourner, la langue de retour, parmi d'autres paramètres.
Prenons notre premier exemple : un champ de recherche par saisie préalable sur les constatations cliniques de SNOMED. Supposons que nous voulions chercher « diabetes mellitus » et obtenir 10 résultats. Voici à quoi pourrait ressembler une requête :
GET https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand
[Query]
url: http://snomed.info/sct?fhir_vs=isa/404684003
count: 10
filter: diabetes mellitus
curl -G 'https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand' \
--data-urlencode 'url=http://snomed.info/sct?fhir_vs=isa/404684003' \
--data-urlencode 'count=10' \
--data-urlencode 'filter=diabetes mellitus'
| Paramètre | Valeur | Explication |
|---|---|---|
url | http://snomed.info/sct?fhir_vs=isa/404684003 | URL implicite pour les concepts de constatation clinique de SNOMED5 |
count | 10 | Nombre de concepts à retourner |
filter | diabetes mellitus | Texte à faire correspondre |
Nous pouvons également fournir un ensemble de valeurs directement dans la requête, ce qui nous permet de concevoir des requêtes sur un système de codes via des propriétés. Par exemple, supposons que nous voulions obtenir tous les médicaments de marque qui contiennent à la fois de la caféine et de l'acétaminophène comme ingrédients.
POST https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand
Content-Type: application/json
{
"resourceType": "Parameters",
"parameter": [
{
"name": "valueSet",
"resource": {
"resourceType": "ValueSet",
"status": "active",
"compose": {
"include": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"filter": [
{ "property": "TTY", "op": "=", "value": "BN" },
{ "property": "tradename_of", "op": "=", "value": "CUI:161" },
{ "property": "tradename_of", "op": "=", "value": "CUI:1886" }
]
}
]
}
}
}
]
}
curl -X POST 'https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand' \
-H 'Content-Type: application/json' \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "valueSet",
"resource": {
"resourceType": "ValueSet",
"status": "active",
"compose": {
"include": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"filter": [
{ "property": "TTY", "op": "=", "value": "BN" },
{ "property": "tradename_of", "op": "=", "value": "CUI:161" },
{ "property": "tradename_of", "op": "=", "value": "CUI:1886" }
]
}
]
}
}
}
]
}'
| Filtre | Valeur | Explication |
|---|---|---|
TTY | BN | Noms de marque seulement |
tradename_of | CUI:161 | Contient de l'acétaminophène |
tradename_of | CUI:1886 | Contient de la caféine |
Prochaine étape
Dans notre prochain article, nous examinerons les canoniques. Comment les ressources terminologiques sont-elles identifiées, quelles conventions sont utilisées, comment le versionnage et la résolution fonctionnent.
- Précédent : Introduction à la terminologie FHIR
- Suivant : Les canoniques — à venir
Footnotes
-
La manière la plus efficace de mettre en œuvre certains de ces exemples est d'utiliser le traitement par lot ; nous isolons les requêtes pour faciliter l'inspection. ↩
-
Nous approfondirons le fonctionnement de ces URL dans un futur article sur les canoniques. ↩
-
La spécification définit en réalité 4 types de données (et 3 supplémentaires). Cependant,
CodeableReferenceest défini en termes deCodeableConceptet les types supplémentaires sont des cas particuliers. C'est pourquoi nous nous concentrons sur les trois premiers. Voir https://build.fhir.org/terminologies.html. ↩ -
Dans un futur article, nous verrons un tutoriel pour configurer un serveur de terminologie afin d'alimenter une application de santé à partir de zéro. ↩
-
Voir https://terminology.hl7.org/en/SNOMEDCT.html pour savoir comment utiliser SNOMED avec la Terminology FHIR. Nous consacrerons un futur article à SNOMED CT. ↩





