FHIR-Ressourcen mit Cloud Storage importieren und exportieren

Auf dieser Seite wird erläutert, wie Sie FHIR-Ressourcen mit den Methoden projects.locations.datasets.fhirStores.import und projects.locations.datasets.fhirStores.export in Cloud Storage exportieren und daraus importieren.

Je nach Format Ihrer FHIR-Daten können Sie zum Laden von Daten in einen FHIR-Speicher die Methode projects.locations.datasets.fhirStores.import oder die Methode projects.locations.datasets.fhirStores.fhir.executeBundle verwenden. Eine Anleitung zur Auswahl einer Methode finden Sie unter FHIR-Import.

Cloud Storage-Berechtigungen festlegen

Bevor Sie FHIR-Ressourcen in Cloud Storage importieren bzw. daraus exportieren können, müssen Sie dem Dienstkonto Cloud Healthcare Service Agent zusätzliche Berechtigungen erteilen. Weitere Informationen finden Sie unter Cloud Storage-Berechtigungen für FHIR-Speicher.

Simulierte Patienteninformationen für DSTU2 oder STU3 generieren

Synthea™ ist ein Simulator zum Generieren von Patientenpopulationsdaten. Wenn Sie Synthea nicht verwenden, fahren Sie mit FHIR-Ressourcen importieren oder FHIR-Ressourcen exportieren fort.

Standardmäßig wird für generierte Synthea™ -Daten die FHIR R4-JSON-Darstellung für Ressourcen verwendet.

Sie können nur Daten in der Version importieren, für die Ihr FHIR-Speicher konfiguriert ist. Führen Sie die folgenden Schritte aus, um Synthea™ FHIR STU3- oder FHIR DSTU2-Daten zu generieren, sodass Sie sie in einen FHIR STU3- oder DSTU2-Speicher importieren können:

  1. Klonen Sie das Repository des Synthea™-Tools von GitHub:

    git clone https://github.com/synthetichealth/synthea.git
    
  2. Führen Sie die Installationsschritte aus.

  3. Öffnen Sie im Verzeichnis synthea die Datei src/main/resources/synthea.properties mit einem Texteditor und nehmen Sie die folgenden Änderungen vor:

    So generieren Sie FHIR STU3-Daten:

    • Alle Werte für *.fhir.export und *.fhir_dstu2.export auf false festlegen
    • Setzen Sie alle *.fhir_stu3.export-Werte auf "true"

    So generieren Sie FHIR-DSTU2-Daten:

    • Alle Werte für *.fhir.export und *.fhir_stu3.export auf false festlegen
    • Setzen Sie alle *.fhir_dstu2.export-Werte auf "true"

    So generieren Sie beispielsweise FHIR STU3-Daten:

    exporter.fhir.export = false
    exporter.fhir_stu3.export = true
    exporter.fhir_dstu2.export = false
    
    exporter.hospital.fhir.export = false
    exporter.hospital.fhir_stu3.export = true
    exporter.hospital.fhir_dstu2.export = false
    
    exporter.practitioner.fhir.export = false
    exporter.practitioner.fhir_stu3.export = true
    exporter.practitioner.fhir_dstu2.export = false
    
  4. Befolgen Sie die Anleitung zum Generieren synthetischer Kundendaten. Die generierten Daten werden für FHIR STU3 in das synthea/output/fhir_stu3 oder für FHIR DSTU2 in das Verzeichnis synthea/output/fhir_dstu2 ausgegeben.

  5. Kopieren Sie die generierten Daten in einen Cloud Storage-Bucket, um sie in einen FHIR-Speicher der Cloud Healthcare API zu importieren. Wenn Sie beispielsweise die Daten in ein Verzeichnis mit dem Namen synthea-data in einem vorhandenen Cloud Storage-Bucket kopieren möchten, führen Sie den folgenden gsutil cp-Befehl aus dem Verzeichnis synthea aus:

    gsutil -m cp output/fhir_stu3/* gs://BUCKET/synthea-data
    
  6. Folgen Sie der Anleitung zum Importieren von FHIR-Ressourcen.

FHIR-Ressourcen importieren

Beim Konfigurieren des Textes der Importanfrage können Sie für ContentStructure einen der folgenden Werte festlegen.

  • CONTENT_STRUCTURE_UNSPECIFIED
  • BUNDLE: Die Quelldatei enthält eine oder mehrere Zeilen mit durch Zeilenumbruch getrennten JSON-Dateien (Ndjson). Jede Zeile ist ein Set, das eine oder mehrere Ressourcen enthält. Setzen Sie den Bundle-Typ auf history, um Ressourcenversionen zu importieren. Wenn Sie ContentStructure nicht angeben, wird standardmäßig BUNDLE verwendet.
  • RESOURCE: Die Quelldatei enthält eine oder mehrere Zeilen mit durch Zeilenumbruch getrennten JSON-Dateien (Ndjson). Jede Zeile ist eine einzelne Ressource.
  • BUNDLE_PRETTY: Die gesamte Quelldatei ist ein JSON-Bundle. Der JSON-Code kann mehrere Zeilen umfassen.
  • RESOURCE_PRETTY: Die gesamte Quelldatei ist eine JSON-Ressource. Der JSON-Code kann mehrere Zeilen umfassen.

Angenommen, Sie importieren eine Datei namens resources.ndjson mit folgendem Inhalt:

{"class":{"code":"IMP","display":"inpatient encounter","system":"http://hl7.org/fhir/v3/ActCode"},"id":"6090e773-3e91-40a7-8fce-1e22f6774c29","reason":[{"text":"The patient had an abnormal heart rate. She was concerned about this."}],"resourceType":"Encounter","status":"finished","subject":{"reference":"Patient/2938bb9e-1f16-429e-8d44-9508ab0e4151"}}
{"class":{"code":"IMP","display":"inpatient encounter","system":"http://hl7.org/fhir/v3/ActCode"},"id":"7101f884-4f02-51b8-9gdf-2f33g7885d30","reason":[{"text":"The patient was experiencing recurrent fevers."}],"resourceType":"Encounter","status":"finished","subject":{"reference":"Patient/3049cc0f-2g27-530f-9e55-0619bc1f5262"}}
{"birthDate":"1970-01-01","gender":"female","id":"2938bb9e-1f16-429e-8d44-9508ab0e4151","name":[{"family":"Smith","given":["Darcy"],"use":"official"}],"resourceType":"Patient"}

Die Datei enthält zwei Ressourcen für Begegnung und eine für Patienten. Da sich jede Ressource in einer separaten Zeile befindet, legen Sie ContentStructure auf RESOURCE fest.

Ihre Daten werden möglicherweise falsch oder gar nicht importiert, wenn ContentStructure nicht mit dem Format Ihrer Daten übereinstimmt. Die obige Beispieldatei wird beispielsweise nur dann korrekt importiert, wenn ContentStructure in der Importanfrage auf RESOURCE gesetzt ist.

In den folgenden Beispielen wird gezeigt, wie FHIR-Ressourcen aus einem Cloud Storage-Bucket importiert werden.

gcloud

Verwenden Sie den Befehl gcloud healthcare fhir-stores import gcs, um FHIR-Ressourcen in einen FHIR-Speicher zu importieren. Geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Speicherort des Objekts in einem Cloud Storage-Bucket. Der Speicherort der Dateien im Bucket ist beliebig und muss nicht genau dem im folgenden Beispiel angegebenen Format entsprechen. Wenn Sie den Speicherort der FHIR-Ressourcen in Cloud Storage angeben, können Sie Platzhalter verwenden, um mehrere Dateien aus einem oder mehreren Verzeichnissen zu importieren. Die folgenden Platzhalter werden unterstützt:
    • Verwenden Sie *, um null oder mehr Nicht-Trennzeichen abzugleichen. Beispiel: gs://BUCKET/DIRECTORY/Example*.ndjson stimmt mit "Example.ndjson" und "Example22.ndjson" in DIRECTORY überein.
    • Verwenden Sie **, um 0 oder mehr Zeichen (einschließlich Trennzeichen) abzugleichen. Muss am Ende eines Pfads und ohne andere Platzhalter im Pfad verwendet werden. Kann auch mit einer Dateinamenerweiterung wie .ndjson verwendet werden, die alle Dateien mit der Dateinamenerweiterung im angegebenen Verzeichnis und in seinen Unterverzeichnissen importiert. Beispiel: gs://BUCKET/DIRECTORY/**.ndjson importiert alle Dateien mit der Endung .ndjson in DIRECTORY und seinen Unterverzeichnissen.
    • Verwenden Sie ? als Platzhalter für genau 1 Zeichen. Beispiel: gs://BUCKET/DIRECTORY/Example?.ndjson stimmt mit "Example1.ndjson" überein, aber nicht mit "Example.ndjson" oder "Example01.ndjson".

Das folgende Beispiel zeigt den Befehl gcloud healthcare fhir-stores import gcs.

gcloud healthcare fhir-stores import gcs FHIR_STORE_ID \
  --dataset=DATASET_ID \
  --location=LOCATION \
  --gcs-uri=gs://BUCKET/DIRECTORY/FHIR_RESOURCE_NAME.ndjson \
  [--content-structure=CONTENT_STRUCTURE]

In der Befehlszeile wird die Vorgangs-ID und nach Abschluss des Vorgangs done angezeigt:

Request issued for: [FHIR_STORE_ID]
Waiting for operation [OPERATION_ID] to complete...done.
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID

Führen Sie den Befehl gcloud healthcare operations describe aus und geben Sie OPERATION_ID aus der Antwort an, um weitere Details des Vorgangs anzuzeigen:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Die Antwort enthält done: true.

done: true
metadata:
'@type': type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata
apiMethodName: google.cloud.healthcare.v1.fhir.FhirService.ImportResources
createTime: 'CREATE_TIME'
endTime: 'END_TIME'
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID
response:
'@type': type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ImportResourcesResponse
fhirStore: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID

API

Verwenden Sie die Methode projects.locations.datasets.fhirStores.import, um FHIR-Ressourcen in einen FHIR-Speicher zu importieren.

  • Der Speicherort der Dateien im Bucket ist beliebig und muss nicht genau dem in den folgenden Beispielen angegebenen Format entsprechen.
  • Wenn Sie den Speicherort der FHIR-Ressourcen in Cloud Storage angeben, können Sie Platzhalter verwenden, um mehrere Dateien aus einem oder mehreren Verzeichnissen zu importieren. Die folgenden Platzhalter werden unterstützt:
    • Verwenden Sie *, um null oder mehr Nicht-Trennzeichen abzugleichen. Beispiel: gs://BUCKET/DIRECTORY/Example*.ndjson stimmt mit "Example.ndjson" und "Example22.ndjson" in DIRECTORY überein.
    • Verwenden Sie **, um 0 oder mehr Zeichen (einschließlich Trennzeichen) abzugleichen. Muss am Ende eines Pfads und ohne andere Platzhalter im Pfad verwendet werden. Kann auch mit einer Dateinamenerweiterung wie .ndjson verwendet werden, die alle Dateien mit der Dateinamenerweiterung im angegebenen Verzeichnis und in seinen Unterverzeichnissen importiert. Beispiel: gs://BUCKET/DIRECTORY/**.ndjson importiert alle Dateien mit der Endung .ndjson in DIRECTORY und seinen Unterverzeichnissen.
    • Verwenden Sie ? als Platzhalter für genau 1 Zeichen. Beispiel: gs://BUCKET/DIRECTORY/Example?.ndjson stimmt mit "Example1.ndjson" überein, aber nicht mit "Example.ndjson" oder "Example01.ndjson".

curl

Wenn Sie FHIR-Ressourcen in einen FHIR-Speicher importieren möchten, senden Sie eine POST-Anfrage und geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Speicherort des Objekts in einem Cloud Storage-Bucket.
  • Ein Zugriffstoken

Das folgende Beispiel zeigt, wie Sie eine einzelne Datei mithilfe einer POST-Anfrage mit curl importieren.

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'contentStructure': 'CONTENT_STRUCTURE',
      'gcsSource': {
        'uri': 'gs://BUCKET/DIRECTORY/FHIR_RESOURCE_FILE'
      }
    }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:import"

Wenn die Anfrage erfolgreich ist, gibt der Server die Antwort im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

Die Antwort enthält einen Vorgangsnamen. Mit der Methode Operation get können Sie den Status des Vorgangs verfolgen:

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Wenn die Anfrage erfolgreich ist, gibt der Server eine Antwort mit dem Status des Vorgangs im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.fhir.FhirService.ImportResources",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ImportResourcesResponse",
  }
}

PowerShell

Wenn Sie FHIR-Ressourcen in einen FHIR-Speicher importieren möchten, senden Sie eine POST-Anfrage und geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Speicherort des Objekts in einem Cloud Storage-Bucket.
  • Ein Zugriffstoken

Das folgende Beispiel zeigt eine POST-Anfrage mit Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/json; charset=utf-8" `
  -Body "{
    'contentStructure': 'CONTENT_STRUCTURE',
    'gcsSource': {
      'uri': 'gs://BUCKET/DIRECTORY/FHIR_RESOURCE_FILE'
    }
  }" `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:import" | Select-Object -Expand Content

Wenn die Anfrage erfolgreich ist, gibt der Server die Antwort im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

Die Antwort enthält einen Vorgangsnamen. Mit der Methode Operation get können Sie den Status des Vorgangs verfolgen:

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-WebRequest `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" | Select-Object -Expand Content

Wenn die Anfrage erfolgreich ist, gibt der Server eine Antwort mit dem Status des Vorgangs im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.fhir.FhirService.ImportResources",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ImportResourcesResponse",
  }
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	healthcare "google.golang.org/api/healthcare/v1"
)

// importsFHIRResource imports an FHIR resource.
func importFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, gcsURI string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.FhirStores

	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s", projectID, location, datasetID, fhirStoreID)
	req := &healthcare.ImportResourcesRequest{
		ContentStructure: "RESOURCE",
		GcsSource: &healthcare.GoogleCloudHealthcareV1FhirGcsSource{
			Uri: gcsURI,
		},
	}

	op, err := storesService.Import(name, req).Do()
	if err != nil {
		return fmt.Errorf("Import: %v", err)
	}

	operationsService := healthcareService.Projects.Locations.Datasets.Operations
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-ticker.C:
			newOp, err := operationsService.Get(op.Name).Do()
			if err != nil {
				return fmt.Errorf("operationsService.Get(%q): %v", op.Name, err)
			}
			if newOp.Done {
				if newOp.Error != nil {
					return fmt.Errorf("import operation %q completed with error: %s", op.Name, newOp.Error.Details)
				}
				return nil
			}
		}
	}
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.FhirStores;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.api.services.healthcare.v1.model.GoogleCloudHealthcareV1FhirGcsSource;
import com.google.api.services.healthcare.v1.model.ImportResourcesRequest;
import com.google.api.services.healthcare.v1.model.Operation;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class FhirStoreImport {
  private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s";
  private static final JsonFactory JSON_FACTORY = new JacksonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void fhirStoreImport(String fhirStoreName, String gcsUri) throws IOException {
    // String fhirStoreName =
    //    String.format(
    //        FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id");
    // String gcsUri = "gs://your-bucket-id/path/to/destination/dir"

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Configure where the store should be imported from.
    GoogleCloudHealthcareV1FhirGcsSource gcsSource =
        new GoogleCloudHealthcareV1FhirGcsSource().setUri(gcsUri);
    ImportResourcesRequest importRequest = new ImportResourcesRequest().setGcsSource(gcsSource);

    // Create request and configure any parameters.
    FhirStores.CloudHealthcareImport request =
        client
            .projects()
            .locations()
            .datasets()
            .fhirStores()
            .healthcareImport(fhirStoreName, importRequest);

    // Execute the request, wait for the operation to complete, and process the results.
    try {
      Operation operation = request.execute();
      while (operation.getDone() == null || !operation.getDone()) {
        // Update the status of the operation with another request.
        Thread.sleep(500); // Pause for 500ms between requests.
        operation =
            client
                .projects()
                .locations()
                .datasets()
                .operations()
                .get(operation.getName())
                .execute();
      }
      System.out.println("FHIR store import complete: " + operation.getResponse());
    } catch (Exception ex) {
      System.out.printf("Error during request execution: %s", ex.toString());
      ex.printStackTrace(System.out);
    }
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const {google} = require('googleapis');
const healthcare = google.healthcare('v1');
const sleep = require('../sleep');

const importFhirResources = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({auth});

  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const fhirStoreId = 'my-fhir-store';
  // const gcsUri = 'my-bucket/my-directory/*.json'
  const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}`;
  const request = {
    name,
    resource: {
      contentStructure: 'RESOURCE',
      gcsSource: {
        uri: `gs://${gcsUri}`,
      },
    },
  };

  const operation = await healthcare.projects.locations.datasets.fhirStores.import(
    request
  );
  const operationName = operation.data.name;

  const operationRequest = {name: operationName};

  // Wait twenty seconds for the LRO to finish.
  await sleep(20000);

  // Check the LRO's status
  const operationStatus = await healthcare.projects.locations.datasets.operations.get(
    operationRequest
  );

  const success = operationStatus.data.metadata.counter.success;

  if (typeof success !== 'undefined') {
    console.log(
      `Import FHIR resources succeeded. ${success} resources imported.`
    );
  } else {
    console.log(
      'Imported FHIR resources failed. Details available in Cloud Logging at the following URL:\n',
      operationStatus.data.metadata.logsUrl
    );
  }
};

importFhirResources();

Python

def import_fhir_resources(project_id, cloud_region, dataset_id, fhir_store_id, gcs_uri):
    """Import resources into the FHIR store by copying them from the
    specified source.
    """
    client = get_client()
    fhir_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, cloud_region, dataset_id
    )
    fhir_store_name = "{}/fhirStores/{}".format(fhir_store_parent, fhir_store_id)

    body = {
        "contentStructure": "CONTENT_STRUCTURE_UNSPECIFIED",
        "gcsSource": {"uri": "gs://{}".format(gcs_uri)},
    }

    # Escape "import()" method keyword because "import"
    # is a reserved keyword in Python
    request = (
        client.projects()
        .locations()
        .datasets()
        .fhirStores()
        .import_(name=fhir_store_name, body=body)
    )

    response = request.execute()
    print("Imported FHIR resources: {}".format(gcs_uri))

    return response

FHIR-Ressourcen exportieren

In den folgenden Beispielen wird gezeigt, wie FHIR-Ressourcen in einen Cloud Storage-Bucket exportiert werden. Wenn Sie FHIR-Ressourcen aus einem FHIR-Speicher exportieren, werden alle Ressourcen in diesem Speicher exportiert.

Während des Exports erstellt die Cloud Healthcare API ein Objekt für jeden Ressourcentyp. Jedes Objekt besteht aus einer durch Zeilenumbruch getrennten JSON-Datei, wobei jede Zeile eine FHIR-Ressource ist. Der Dateiname enthält den Ressourcentyp, z. B. 1264567891234567_Patient.ndjson.

gcloud

Verwenden Sie den Befehl gcloud healthcare fhir-stores export gcs, um FHIR-Instanzen in einen Cloud Storage-Bucket zu exportieren. Geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Cloud Storage-Ziel-Bucket oder das Cloud Storage-Ziel-Verzeichnis. Schreiben Sie in einen Cloud Storage-Bucket oder ein Cloud Storage-Verzeichnis und nicht in ein Objekt, da die Cloud Healthcare API ein Objekt für jeden Ressourcentyp erstellt. Jedes Objekt besteht aus durch Zeilenumbruch getrennten JSON-Dateien, wobei jede Zeile eine FHIR-Ressource ist. Wenn Sie ein nicht vorhandenes Verzeichnis angeben, wird es erstellt.

Das folgende Beispiel zeigt den Befehl gcloud healthcare fhir-stores export gcs.

gcloud healthcare fhir-stores export gcs FHIR_STORE_ID \
  --dataset=DATASET_ID \
  --location=LOCATION \
  --gcs-uri=gs://BUCKET/DIRECTORY

In der Befehlszeile wird die Vorgangs-ID angezeigt:

Waiting for operation [OPERATION_ID] to complete...done.
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID

Führen Sie den Befehl gcloud healthcare operations describe aus und geben Sie OPERATION_ID aus der Antwort an, um den Status des Vorgangs anzuzeigen:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Nach Abschluss des Befehls enthält die Antwort done.

metadata:
'@type': type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata
apiMethodName: google.cloud.healthcare.v1.fhir.FhirService.ExportFhirData
createTime: "CREATE_TIME"
endTime: "END_TIME"
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID
response:
'@type': type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ExportResourcesResponse
fhirStore: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID
resourceCount: 'RESOURCE_COUNT'

API

Verwenden Sie zum Exportieren von FHIR-Ressourcen die Methode projects.locations.datasets.fhirStores.export.

  • Schreiben Sie in einen Cloud Storage-Bucket oder ein Cloud Storage-Verzeichnis und nicht in ein Objekt, da die Cloud Healthcare API für jeden Ressourcentyp eine durch Zeilenumbruch getrennte JSON-Datei erstellt. In jeder JSON-Datei ist jede Zeile eine FHIR-Ressource.
  • Wenn der Befehl ein nicht vorhandenes Verzeichnis angibt, wird das Verzeichnis erstellt.

curl

Wenn Sie FHIR-Ressourcen exportieren möchten, senden Sie eine POST-Anfrage und geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Cloud Storage-Ziel-Bucket
  • Ein Zugriffstoken

Das folgende Beispiel zeigt eine POST-Anfrage mit curl.

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'gcsDestination': {
        'uriPrefix': 'gs://BUCKET/DIRECTORY'
      }
    }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:export"

Wenn die Anfrage erfolgreich ist, gibt der Server die Antwort im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

Die Antwort enthält einen Vorgangsnamen. Sie können den Status des Vorgangs mit der Methode Operation get verfolgen:

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Wenn die Anfrage erfolgreich ist, gibt der Server eine Antwort mit dem Status des Vorgangs im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.fhir.FhirService.ExportResources",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ExportResourcesResponse",
  }
}

PowerShell

Wenn Sie FHIR-Ressourcen exportieren möchten, senden Sie eine POST-Anfrage und geben Sie die folgenden Informationen an:

  • Der Name des übergeordneten Datasets
  • Der Name des FHIR-Speichers
  • Der Cloud Storage-Ziel-Bucket oder das Cloud Storage-Ziel-Verzeichnis. Schreiben Sie in einen Cloud Storage-Bucket oder ein Cloud Storage-Verzeichnis und nicht in ein Objekt, da die Cloud Healthcare API ein Objekt für jeden Ressourcentyp erstellt. Jedes Objekt besteht aus durch Zeilenumbruch getrennten JSON-Dateien, wobei jede Zeile eine FHIR-Ressource ist.
  • Ein Zugriffstoken

Das folgende Beispiel zeigt eine POST-Anfrage mit Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/json; charset=utf-8" `
  -Body "{
    'gcsDestination': {
      'uriPrefix': 'gs://BUCKET/DIRECTORY'
    }
  }" `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:export" | Select-Object -Expand Content

Wenn die Anfrage erfolgreich ist, gibt der Server die Antwort im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

Die Antwort enthält einen Vorgangsnamen. Mit der Methode Operation get können Sie den Status des Vorgangs verfolgen:

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-WebRequest `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" | Select-Object -Expand Content

Wenn die Anfrage erfolgreich ist, gibt der Server eine Antwort mit dem Status des Vorgangs im JSON-Format zurück:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.fhir.FhirService.ExportResources",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ExportResourcesResponse",
  }
}

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	healthcare "google.golang.org/api/healthcare/v1"
)

// exportFHIRResource exports the resources in the FHIR store.
func exportFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, gcsURIPrefix string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.FhirStores

	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s", projectID, location, datasetID, fhirStoreID)
	req := &healthcare.ExportResourcesRequest{
		GcsDestination: &healthcare.GoogleCloudHealthcareV1FhirGcsDestination{
			UriPrefix: gcsURIPrefix,
		},
	}

	op, err := storesService.Export(name, req).Do()
	if err != nil {
		return fmt.Errorf("Export: %v", err)
	}

	operationsService := healthcareService.Projects.Locations.Datasets.Operations
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-ticker.C:
			newOp, err := operationsService.Get(op.Name).Do()
			if err != nil {
				return fmt.Errorf("operationsService.Get(%q): %v", op.Name, err)
			}
			if newOp.Done {
				if newOp.Error != nil {
					return fmt.Errorf("export operation %q completed with error: %v", op.Name, newOp.Error)
				}
				return nil
			}
		}
	}
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.FhirStores;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.api.services.healthcare.v1.model.ExportResourcesRequest;
import com.google.api.services.healthcare.v1.model.GoogleCloudHealthcareV1FhirGcsDestination;
import com.google.api.services.healthcare.v1.model.Operation;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class FhirStoreExport {
  private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s";
  private static final JsonFactory JSON_FACTORY = new JacksonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void fhirStoreExport(String fhirStoreName, String gcsUri) throws IOException {
    // String fhirStoreName =
    //    String.format(
    //        FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id");
    // String gcsUri = "gs://your-bucket-id/path/to/destination/dir"

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Configure where the store will be exported too.
    GoogleCloudHealthcareV1FhirGcsDestination gcsDestination =
        new GoogleCloudHealthcareV1FhirGcsDestination().setUriPrefix(gcsUri);
    ExportResourcesRequest exportRequest =
        new ExportResourcesRequest().setGcsDestination(gcsDestination);

    // Create request and configure any parameters.
    FhirStores.Export request =
        client.projects().locations().datasets().fhirStores().export(fhirStoreName, exportRequest);

    // Execute the request, wait for the operation to complete, and process the results.
    try {
      Operation operation = request.execute();
      while (operation.getDone() == null || !operation.getDone()) {
        // Update the status of the operation with another request.
        Thread.sleep(500); // Pause for 500ms between requests.
        operation =
            client
                .projects()
                .locations()
                .datasets()
                .operations()
                .get(operation.getName())
                .execute();
      }
      System.out.println("Fhir store export complete." + operation.getResponse());
    } catch (Exception ex) {
      System.out.printf("Error during request execution: %s", ex.toString());
      ex.printStackTrace(System.out);
    }
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const {google} = require('googleapis');
const healthcare = google.healthcare('v1');
const sleep = require('../sleep');

const exportFhirResourcesGcs = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({auth});

  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const fhirStoreId = 'my-fhir-store';
  // const gcsUri = 'my-bucket/my-directory'
  const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}`;
  const request = {
    name,
    resource: {
      gcsDestination: {
        // The destination location in Cloud Storage for the FHIR resources
        uriPrefix: `gs://${gcsUri}`,
      },
    },
  };

  const operation = await healthcare.projects.locations.datasets.fhirStores.export(
    request
  );
  const operationName = operation.data.name;

  // Wait ten seconds for the LRO to finish
  await sleep(10000);

  // Check the LRO's status
  const operationStatus = await healthcare.projects.locations.datasets.operations.get(
    {name: operationName}
  );

  if (typeof operationStatus.data.metadata.counter !== 'undefined') {
    console.log('Exported FHIR resources successfully');
  } else {
    console.log('Export failed');
  }
};

exportFhirResourcesGcs();

Python

def export_fhir_store_gcs(project_id, cloud_region, dataset_id, fhir_store_id, gcs_uri):
    """Export resources to a Google Cloud Storage bucket by copying
    them from the FHIR store."""
    client = get_client()
    fhir_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, cloud_region, dataset_id
    )
    fhir_store_name = "{}/fhirStores/{}".format(fhir_store_parent, fhir_store_id)

    body = {"gcsDestination": {"uriPrefix": "gs://{}/fhir_export".format(gcs_uri)}}

    request = (
        client.projects()
        .locations()
        .datasets()
        .fhirStores()
        .export(name=fhir_store_name, body=body)
    )

    response = request.execute()
    print("Exported FHIR resources to bucket: gs://{}".format(gcs_uri))

    return response

Fehlerbehebung bei FHIR-Import- und Exportanfragen

Wenn während einer FHIR-Import- oder Exportanfrage Fehler auftreten, werden die Fehler in Cloud Logging protokolliert. Weitere Informationen finden Sie unter Fehlerlogs in Cloud Logging ansehen.