Add howto-fhir-date-parameter.md
This commit is contained in:
@@ -0,0 +1,164 @@
|
|||||||
|
# HowTo: Der FHIR `date`-Suchparameter – Präfixe, Intervalle und Kombinationen richtig verstehen
|
||||||
|
|
||||||
|
Wer FHIR-Server baut oder abfragt, stolpert früher oder später über den
|
||||||
|
`date`-Suchparameter. Auf den ersten Blick sieht er simpel aus –
|
||||||
|
`?date=2023-06-15` – aber sobald Präfixe wie `ge`, `sa` oder `ap` ins Spiel
|
||||||
|
kommen und mehrere `date`-Parameter kombiniert werden, wird es schnell
|
||||||
|
unübersichtlich. Dieser Artikel bringt Ordnung rein: Schritt für Schritt, mit
|
||||||
|
Zeitleisten-Grafiken zu jedem Fall.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Das Grundprinzip: FHIR vergleicht Intervalle, keine Zeitpunkte
|
||||||
|
|
||||||
|
Der wichtigste gedankliche Reset zuerst: FHIR behandelt Datumswerte nie als
|
||||||
|
exakten Zeitpunkt, sondern immer als **Intervall**. Wie breit dieses Intervall
|
||||||
|
ist, hängt von der Precision des angegebenen Werts ab:
|
||||||
|
|
||||||
|
- `2023` → das ganze Jahr 2023
|
||||||
|
- `2023-06` → der ganze Juni 2023
|
||||||
|
- `2023-06-15` → der ganze 15. Juni 2023 (00:00–24:00 Uhr)
|
||||||
|
- `2023-06-15T10:00:00` → (fast) ein exakter Zeitpunkt
|
||||||
|
|
||||||
|
Jeder Vergleichsoperator vergleicht anschließend **zwei Intervalle**
|
||||||
|
miteinander: das Such-Intervall aus deinem Query-Parameter und das
|
||||||
|
Resource-Intervall aus dem Feld der Ressource (z. B. `Patient.birthDate` oder
|
||||||
|
`Encounter.period`).
|
||||||
|
|
||||||
|
### Ohne Präfix = `eq`, aber die Precision entscheidet mit
|
||||||
|
|
||||||
|
Gibst du kein Präfix an, nimmt der Server `eq` an. Das Resource-Datum muss
|
||||||
|
dann **vollständig** innerhalb deines Such-Intervalls liegen. Je gröber die
|
||||||
|
Precision, desto breiter das Intervall – und desto mehr Resource-Werte passen
|
||||||
|
hinein:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`date=2023-06-15` matched nur diesen einen Tag. `date=2023-06` matched dagegen
|
||||||
|
jeden Tag im Juni – auch den 15. Das ist der häufigste Stolperstein für
|
||||||
|
Einsteiger: eine „ungenaue" Suchanfrage ist nicht strenger, sondern lockerer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Die neun Präfixe im Überblick
|
||||||
|
|
||||||
|
FHIR definiert insgesamt neun Präfixe für `date`. Jeder davon beschreibt eine
|
||||||
|
andere Beziehung zwischen Such-Intervall (rot gestrichelt in der Grafik) und
|
||||||
|
Treffer-Bereich (grün/farbig schattiert):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
| Präfix | Name | Bedeutung |
|
||||||
|
|---|---|---|
|
||||||
|
| `eq` | gleich | Resource-Intervall liegt vollständig im Such-Intervall |
|
||||||
|
| `ne` | ungleich | Komplement von `eq` |
|
||||||
|
| `gt` | größer als | Resource-Datum beginnt nach dem Ende des Such-Intervalls |
|
||||||
|
| `lt` | kleiner als | Resource-Datum endet vor dem Beginn des Such-Intervalls |
|
||||||
|
| `ge` | größer/gleich | Beginnt am oder nach Beginn des Such-Intervalls |
|
||||||
|
| `le` | kleiner/gleich | Endet am oder vor Ende des Such-Intervalls |
|
||||||
|
| `sa` | starts after | Beginnt vollständig **nach** dem Ende des Such-Intervalls |
|
||||||
|
| `eb` | ends before | Endet vollständig **vor** dem Beginn des Such-Intervalls |
|
||||||
|
| `ap` | approximately | Ungefähre Übereinstimmung, Toleranz serverabhängig |
|
||||||
|
|
||||||
|
**Praxis-Tipp:** `sa`/`eb` unterscheiden sich von `gt`/`lt` nur spürbar bei
|
||||||
|
Resource-Feldern, die selbst ein **Intervall** sind (`Period`, z. B.
|
||||||
|
`Encounter.period`). Bei einem einzelnen Zeitpunkt-Feld ist der Unterschied
|
||||||
|
meist nicht beobachtbar – `gt` reicht schon, wenn die Period *beginnt* nach
|
||||||
|
dem Suchdatum; `sa` verlangt, dass die *gesamte* Period danach liegt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Mehrere `date`-Parameter kombinieren
|
||||||
|
|
||||||
|
In der Praxis reicht ein einzelner Präfix selten – meist willst du einen
|
||||||
|
**Bereich** definieren. FHIR-Server verknüpfen mehrere `date`-Parameter in
|
||||||
|
derselben Query immer per **UND**. Vier typische Muster:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
| Kombination | Beispiel | Charakter |
|
||||||
|
|---|---|---|
|
||||||
|
| `ge` + `le` | `ge2023-01-01&le2023-12-31` | Geschlossenes Intervall (beide Grenzen inklusive) |
|
||||||
|
| `gt` + `lt` | `gt2023-01-01<2023-12-31` | Offenes Intervall (beide Grenzen exklusive) |
|
||||||
|
| `sa` + `eb` | `sa2023-01-01&eb2023-12-31` | Strikt getrennter Bereich, primär für Period-Werte |
|
||||||
|
| `ge` + `lt` | `ge2023-06-01<2023-07-01` | Halboffenes Intervall `[start, ende)` – Standardmuster für „genau ein Monat" |
|
||||||
|
|
||||||
|
Wenn du in Timestamp-lastigen ETL-Pipelines mit `[start, ende)` arbeitest,
|
||||||
|
kommt dir `ge` + `lt` bekannt vor – es ist exakt dasselbe Muster wie bei
|
||||||
|
klassischen Zeitfenster-Queries in SQL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Die vollständige 3×3-Matrix aller Bereichs-Kombinationen
|
||||||
|
|
||||||
|
Die vier Muster oben sind nur die gebräuchlichsten. Tatsächlich lässt sich
|
||||||
|
**jede** Untergrenze mit **jeder** Obergrenze kombinieren:
|
||||||
|
|
||||||
|
- Untergrenzen: `ge`, `gt`, `sa`
|
||||||
|
- Obergrenzen: `le`, `lt`, `eb`
|
||||||
|
|
||||||
|
Das ergibt 3 × 3 = **9 mögliche Kombinationen**, alle spec-konform:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Sie unterscheiden sich nur darin, ob die jeweilige Grenze inklusiv
|
||||||
|
(durchgezogene Linie) oder exklusiv (gestrichelte Linie) ist, und ob es sich
|
||||||
|
um einen einfachen Werte-Vergleich (`ge`/`gt`/`le`/`lt`) oder einen strengen
|
||||||
|
Period-Vergleich (`sa`/`eb`) handelt. Es gibt **keine explizite
|
||||||
|
Ausschluss-Regel** im FHIR-Standard – jede Zelle dieser Matrix ist eine
|
||||||
|
gültige, funktionierende Query.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Sonderfälle: Wenn Kombinationen redundant oder widersprüchlich werden
|
||||||
|
|
||||||
|
Nicht jede syntaktisch gültige Kombination ist auch praktisch sinnvoll. Drei
|
||||||
|
Kategorien solltest du kennen, bevor du sie versehentlich in einer
|
||||||
|
generierten Query landen lässt:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### a) Redundante Kombinationen
|
||||||
|
Ändern nichts am Ergebnis, sind aber technisch kein Fehler:
|
||||||
|
- `eq` + eine Grenze, die vom `eq`-Intervall ohnehin erfüllt wird
|
||||||
|
(`eq2023-06-15&ge2020-01-01`) – die Zusatzbedingung ist überflüssig.
|
||||||
|
- Zwei Bedingungen desselben Richtungstyps
|
||||||
|
(`ge2020-01-01&ge2023-01-01`) – nur die strengere (spätere) Untergrenze
|
||||||
|
wirkt effektiv.
|
||||||
|
|
||||||
|
### b) Kombinationen mit garantiert leerem Ergebnis
|
||||||
|
Strukturell unmöglich zu erfüllen:
|
||||||
|
- `eq` + `ne` auf denselben Wert (`eq2023-06-15&ne2023-06-15`) –
|
||||||
|
sich gegenseitig ausschließende Bedingungen.
|
||||||
|
- Untergrenze liegt zeitlich nach der Obergrenze
|
||||||
|
(`ge2023-06-01&le2023-01-01`) – kein Datum erfüllt beides gleichzeitig.
|
||||||
|
|
||||||
|
Der Server wird solche Queries **syntaktisch akzeptieren** und einfach eine
|
||||||
|
leere Ergebnismenge zurückgeben – kein Fehler, aber auch keine hilfreiche
|
||||||
|
Rückmeldung. Es lohnt sich, so etwas clientseitig vorab zu validieren.
|
||||||
|
|
||||||
|
### c) Ungewöhnliche, aber gültige Sonderfälle
|
||||||
|
- **Drei oder mehr `date`-Parameter**, z. B. ein Jahresbereich mit
|
||||||
|
ausgeschlossenem Einzeltag: `ge2023-01-01&le2023-12-31&ne2023-06-15`.
|
||||||
|
- **`ap` kombiniert mit einer Grenze**, z. B.
|
||||||
|
`ap2023-06-15&ge2023-01-01` – selten genutzt, da `ap` selbst schon
|
||||||
|
unscharf ist und die Toleranzberechnung serverabhängig bleibt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Praxis-Empfehlungen zum Schluss
|
||||||
|
|
||||||
|
- Für einfache Bereichsfilter ist **`ge` + `lt`** (halboffenes Intervall) meist
|
||||||
|
das robusteste Muster – es vermeidet Rundungsprobleme an der
|
||||||
|
Precision-Grenze (kein Off-by-one bei „bis einschließlich 31.12.").
|
||||||
|
- **`sa`/`eb`** nur einsetzen, wenn das Zielfeld tatsächlich ein `Period`- oder
|
||||||
|
`Range`-Element ist. Bei einfachen `date`/`dateTime`-Feldern liefern sie in
|
||||||
|
der Regel dasselbe Ergebnis wie `gt`/`lt` – der zusätzliche Ausdruck bringt
|
||||||
|
dann keinen Mehrwert.
|
||||||
|
- Vor dem Absetzen einer Multi-Parameter-Query lohnt sich ein kurzer Check auf
|
||||||
|
logische Konsistenz zwischen Unter- und Obergrenze, um leere Ergebnisse
|
||||||
|
durch Konfigurationsfehler in der eigenen Pipeline zu vermeiden.
|
||||||
|
|
||||||
|
Mit diesen fünf Grafiken im Hinterkopf – ohne Präfix, alle neun Präfixe
|
||||||
|
einzeln, typische Kombinationen, die volle 3×3-Matrix und die Sonderfälle –
|
||||||
|
sollte die nächste `date`-Query im FHIR-Suchparameter kein Rätsel mehr sein.
|
||||||
Reference in New Issue
Block a user