FHIR-Ressourcen sind auf Interoperabilität optimiert, während Analyseplattformen wie Databricks am besten mit Tabellen arbeiten. Healthcare-Analyseteams stoßen ständig auf diese Lücke – sie benötigen FHIR-Daten in Databricks für Reporting, Forschung, maschinelles Lernen und populationsbezogene Gesundheitsanalysen, aber die Daten kommen als verschachteltes JSON statt als Zeilen an.
Seit Aidbox 2605 können Sie diese Lücke direkt schließen: Exportieren Sie SQL-on-FHIR ViewDefinitions direkt in verwaltete Delta-Tabellen des Databricks Unity Catalog. Dieser Artikel zeigt, wie Sie diese Pipeline aufbauen – mit:
$viewdefinition-exportfür Snapshots und BackfillsAidboxTopicDestinationfür Continuous Delivery mit automatischem initialem Export
Warum Databricks für FHIR-Analysen?
FHIR ist ein gutes Format für den Austausch von Gesundheitsdaten, aber es ist keine praktische Form für Analysen. Analyseteams möchten Kohorten abfragen, Dashboards erstellen, klinische Daten mit operativen Daten verknüpfen und Datensätze für Forschung oder maschinelles Lernen vorbereiten – und Databricks bietet ihnen eine Lakehouse-Plattform, die genau dafür entwickelt wurde:
- Delta Lake-Tabellen für analytischen Speicher
- Unity Catalog für Governance
- Databricks SQL für Abfragen
- Notebooks und Jobs für die Datenverarbeitung
- ML- und KI-Workflows auf denselben Tabellen
Das fehlende Glied ist die FHIR-zu-Tabellen-Transformation – und genau das liefern SQL-on-FHIR ViewDefinitions: Sie definieren, wie FHIR-Ressourcen zu analytischen Zeilen werden, bevor diese Zeilen in Databricks landen.
FHIR-Ressourcen in Analysetabellen umwandeln
FHIR-Ressourcen sind verschachteltes JSON, aber die meisten Analyse-Workloads benötigen relationale Tabellen. Genau diese Diskrepanz ist in der Regel der Ausgangspunkt für Probleme – jemand baut eine ETL-Pipeline, jemand anderes pflegt sie, und sechs Monate später ist die Pipeline zu einem eigenständigen Produkt geworden.
Aidbox löst dies mit SQL-on-FHIR: Definieren Sie eine ViewDefinition, und FHIR-Ressourcen werden zu Zeilen.
{
"resourceType": "ViewDefinition",
"id": "patient_flat",
"resource": "Patient",
"select": [
{
"column": [
{ "name": "id", "path": "id" },
{ "name": "ts", "path": "getAidboxTs()" },
{ "name": "gender", "path": "gender" },
{ "name": "birth_date", "path": "birthDate" },
{ "name": "family_name", "path": "name.where(use = 'official').family.first()" },
{ "name": "given_name", "path": "name.where(use = 'official').given.first()" }
]
}
]
}
Was dies bewirkt
Diese ViewDefinition nimmt Patient-Ressourcen und wandelt sie in flache analytische Zeilen um.
resource: Patientwählt den FHIR-Quellressourcentyp aus.id,gender,birth_date,family_nameundgiven_namewerden zu Tabellenspalten.getAidboxTs()fügt eine Zeitstempelspalte hinzu, die für inkrementelle Exporte verwendet wird.- Nach der Materialisierung stellt Aidbox das Ergebnis als
sof.patient_flatbereit.
Die View materialisieren:
POST /fhir/ViewDefinition/patient_flat/$materialize
Eine Patient-Ressource:
{
"resourceType": "Patient",
"id": "patient-1",
"gender": "male",
"birthDate": "1990-01-15",
"name": [
{
"use": "official",
"family": "Smith",
"given": ["John"]
}
]
}
wird zu einer abfragbaren Zeile:
SELECT id, ts, gender, birth_date, family_name, given_name
FROM sof.patient_flat;
| id | ts | gender | birth_date | family_name | given_name |
|---|---|---|---|---|---|
| patient-1 | 2026-06-09T10:15:00Z | male | 1990-01-15 | Smith | John |
Aidbox stellt das Ergebnis als PostgreSQL-View sof.patient_flat bereit, die als Quelle für sowohl Batch-Exporte als auch Continuous Delivery dient.
Noch nicht mit SQL-on-FHIR vertraut?
Lesen Sie unsere Artikel:
Continuous Delivery von FHIR nach Databricks
Aidbox themenbasierte Subscriptions bilden die Ereignisschicht hinter Continuous Delivery – mit At-least-once-Semantik und einem Append-only-Ziel. Sie definieren ein AidboxSubscriptionTopic für die Ressourcenänderungen, die Sie verfolgen möchten, und hängen dann ein AidboxTopicDestination an, das bestimmt, wohin diese Ereignisse geleitet werden. In diesem Fall ist das Ziel kein Webhook oder eine Warteschlange – es ist ein Data-Lakehouse-Writer, der Zeilen aus der SQL-on-FHIR ViewDefinition entnimmt und an Databricks liefert.
Ein Topic erstellen, das auf Patient-Änderungen lauscht:
POST /fhir/AidboxSubscriptionTopic
{
"resourceType": "AidboxSubscriptionTopic",
"url": "http://example.org/subscriptions/patient-updates",
"status": "active",
"trigger": [
{
"resource": "Patient",
"supportedInteraction": ["create", "update", "delete"]
}
]
}
Ein Data-Lakehouse-Ziel erstellen:
{
"resourceType": "AidboxTopicDestination",
"id": "patient-databricks",
"topic": "http://example.org/subscriptions/patient-updates",
"kind": "data-lakehouse-at-least-once",
"parameter": [
// ... databricks params ...
{ "name": "viewDefinition",
"valueString": "patient_flat"
},
{ "name": "batchSize",
"valueUnsignedInt": 50
},
{ "name": "sendIntervalMs",
"valueUnsignedInt": 5000
}
]
}
Was dies bewirkt
Dieses Ziel sendet SQL-on-FHIR-Zeilen an Databricks, sobald eine passende FHIR-Ressource sich ändert.
topic– das Subscription-Topic, auf das gelauscht wird.viewDefinition– die abgeflachte Tabellenstruktur, die gesendet wird.batchSize– wie viele Zeilen in einen Lieferungs-Batch eingehen.sendIntervalMs– wie oft ausstehende Zeilen geleert werden.// ... databricks params ...– Databricks-spezifische Verbindungsfelder, der Übersichtlichkeit halber weggelassen. Siehe Data Lakehouse AidboxTopicDestination.
Einen Patienten anlegen:
POST /fhir/Patient
{
"name": [
{
"use": "official",
"family": "Smith",
"given": ["John"]
}
],
"gender": "male",
"birthDate": "1990-01-15"
}
Databricks prüfen:
SELECT id, ts, gender, birth_date, family_name, given_name, is_deleted
FROM aidbox_export.fhir.patients;
| id | ts | gender | birth_date | family_name | given_name | is_deleted |
|---|---|---|---|---|---|---|
| patient-1 | 2026-06-09T10:15:00Z | male | 1990-01-15 | Smith | John | 0 |
Die Export-Engine fügt der Zieltabelle eine is_deleted-Spalte hinzu, damit nachgelagerte Abfragen gelöschte Ressourcen herausfiltern können, ohne deren Historie zu verlieren.
Der initiale FHIR-Export ist inklusive
Die meisten Systeme enthalten bereits Daten, bevor der erste Stream startet. Wenn AidboxTopicDestination gestartet wird, exportiert es automatisch den aktuellen Zustand jeder Zeile aus der ViewDefinition, bevor es auf Live-Delivery umschaltet – kein separater Bootstrap-Job, kein benutzerdefiniertes Migrationsskript, keine doppelte Pipeline. Historische Zeilen werden zum Ausgangspunkt, und neue Aktualisierungen laufen weiterhin über den Live-Stream.
Dies ist das Standardverhalten. Wenn Sie nur neue Daten ab dem Zeitpunkt der Erstellung des Ziels möchten, fügen Sie skipInitialExport: true zum parameter-Array des Ziels hinzu:
{ "name": "skipInitialExport", "valueBoolean": true }
Mehr dazu in der Aidbox-Dokumentation:
👉 Initialer Export für Data Lakehouse AidboxTopicDestination
Batch-Export von FHIR nach Delta Lake
Benötigen Sie einen einmaligen Snapshot statt eines kontinuierlichen Streams? Verwenden Sie $viewdefinition-export.
POST /fhir/ViewDefinition/$viewdefinition-export
Prefer: respond-async
{
"resourceType": "Parameters",
"parameter": [
{
"name": "view",
"part": [
{
"name": "name",
"valueString": "patient_flat"
},
{
"name": "viewReference",
"valueReference": {
"reference": "ViewDefinition/patient_flat"
}
}
]
},
{
"name": "kind",
"valueString": "data-lakehouse"
}
// ... databricks parameters ...
]
}
Einmaliger Export
Verwenden Sie $viewdefinition-export, wenn Sie einen kontrollierten Batch-Job statt Continuous Delivery benötigen.
Typische Anwendungsfälle:
- einmalige Snapshots
- historische Backfills
- geplante Exporte
- Recovery-Jobs
- inkrementelle Export-Schleifen mit
_since
Die Operation läuft asynchron und gibt im Content-Location-Header eine Status-URL zurück.
Antwort:
202 Accepted
Content-Location: /fhir/ViewDefinition/$viewdefinition-export/status/<export-id>
Status prüfen:
GET /fhir/ViewDefinition/$viewdefinition-export/status/<export-id>
Wenn der Export abgeschlossen ist:
{
"resourceType": "Parameters",
"parameter": [
{
"name": "status",
"valueCode": "completed"
},
{
"name": "output",
"part": [
{
"name": "location",
"valueUri": "databricks-uc:aidbox_export.fhir.patients"
}
]
}
]
}
Die resultierende Tabelle in Databricks SQL abfragen:
SELECT id, ts, gender, birth_date, family_name, given_name, is_deleted
FROM aidbox_export.fhir.patients;
| id | ts | gender | birth_date | family_name | given_name | is_deleted |
|---|---|---|---|---|---|---|
| patient-1 | 2026-06-09T10:15:00Z | male | 1990-01-15 | Smith | John | 0 |
| patient-2 | 2026-06-09T10:18:00Z | female | 1984-07-22 | Garcia | Maria | 0 |
| patient-3 | 2026-06-09T10:24:00Z | other | 2001-03-08 | Chen | Alex | 0 |
| patient-4 | 2026-06-09T10:31:00Z | female | 1976-11-30 | Okafor | Amara | 0 |
Inkrementelle FHIR-Exporte
Benötigen Sie einen nächtlichen inkrementellen Export statt eines kontinuierlichen Streams? Verwenden Sie _since. Aidbox filtert Zeilen anhand der Zeitstempelspalte der ViewDefinition, die aus getAidboxTs() generiert wird, sodass der Export nur Zeilen enthält, die nach dem von Ihnen übergebenen Wasserzeichen geändert wurden. Verwenden Sie dieselbe oben gezeigte $viewdefinition-export-Anfrage und fügen Sie einen weiteren Parameter hinzu:
{
"name": "_since",
"valueInstant": "2026-01-01T00:00:00Z"
}
Um inkrementelle Exporte nach Zeitplan auszuführen, setzen Sie _since nach jedem Durchlauf weiter:
$viewdefinition-exportmit_sinceausführen.- Warten, bis der Exportstatus
completedist. exportEndTimeaus der abgeschlossenen Antwort auslesen und speichern.- Diesen Wert als
_sinceim nächsten Durchlauf verwenden.
So erhalten Sie geplante inkrementelle Exporte, ohne eine separate Pipeline zur Änderungsverfolgung aufzubauen.
AidboxTopicDestination vs. $viewdefinition-export
AidboxTopicDestination | $viewdefinition-export | |
|---|---|---|
| Lieferung | Kontinuierlich, ereignisgesteuert | Einmalig, auf Anfrage |
| Initialer Export | Automatisch | Manuell |
| Aktualisierungen | Nahezu in Echtzeit, pro Ressourcenänderung | Batch, pro Anfrage |
| Inkrementell | Integriert über Subscription-Topics | Manuell über _since |
| Beste Verwendung | Produktionspipelines, die Databricks-Tabellen kontinuierlich aktuell halten | Snapshots, historische Backfills, geplante Jobs, Recovery und Replay |
Wie der FHIR-nach-Delta-Lake-Export funktioniert
Sowohl der initiale Export von AidboxTopicDestination als auch $viewdefinition-export verwenden dieselbe Export-Engine, die:
- Zeilen aus der materialisierten PostgreSQL-View
sof.<view>liest. - Den Export in mehrere Chunks aufteilt.
- Delta-Staging-Tabellen nach S3 schreibt.
- Eine abschließende
MERGE INTO-Operation gegen die verwaltete Unity-Catalog-Tabelle ausführt.
Das Ergebnis ist eine Databricks Delta Lake-Tabelle, die Sie über Databricks SQL, Notebooks, Dashboards oder nachgelagerte Analyse-Tools abfragen können.
Bei großen Exporten können Chunks parallel über mehrere Aidbox-Pods verarbeitet werden.
Weitere FHIR-Analyseziele
Databricks ist nicht das einzige unterstützte Analyseziel. Wenn Sie ClickHouse verwenden, lesen Sie ClickHouse AidboxTopicDestination; für BigQuery lesen Sie BigQuery AidboxTopicDestination. Beide Ziele verwenden denselben SQL-on-FHIR-ViewDefinition-Ansatz und dasselbe Continuous-Delivery-Modell.
Über Exporte hinaus
Für eine engere Integration kann Aidbox nativ auf Databricks Lakebase betrieben werden – die Architektur finden Sie unter Building a FHIR-native health data platform on Databricks Lakebase, oder besuchen Sie Health Samurai + Databricks für Details zur Partnerschaft.
Fazit
FHIR-Ressourcen sind auf Interoperabilität optimiert, Databricks ist auf Analysen optimiert. SQL-on-FHIR ViewDefinitions überbrücken diese Lücke, indem sie FHIR-Ressourcen in analytische Tabellen umwandeln. Verwenden Sie $viewdefinition-export, wenn Sie Snapshots, Backfills oder inkrementelle Exporte benötigen, und AidboxTopicDestination, wenn Sie Continuous Delivery und eine automatische initiale Beladung benötigen. In jedem Fall empfängt Databricks Delta Lake flache analytische Zeilen statt verschachteltem FHIR-JSON.
Weiterführende Lektüre:
🤔 Haben Sie eine Frage?
Fragen Sie uns im Zulip-Chat: https://connect.health-samurai.io/



