165 lines
7.4 KiB
Markdown
165 lines
7.4 KiB
Markdown
# 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.
|