Importa ed esporta le risorse FHIR utilizzando Cloud Storage

In questa pagina viene spiegato come esportare e importare le risorse FHIR in e da Cloud Storage utilizzando i metodi projects.locations.datasets.fhirStores.import e projects.locations.datasets.fhirStores.export.

A seconda del formato dei dati FHIR, per caricarli in un archivio FHIR puoi utilizzare il metodo projects.locations.datasets.fhirStores.import o il metodo projects.locations.datasets.fhirStores.fhir.executeBundle. Per indicazioni sulla scelta di un metodo, consulta Importazione FHIR.

Impostazione delle autorizzazioni Cloud Storage

Prima di esportare e importare le risorse FHIR in e da Cloud Storage, devi concedere autorizzazioni aggiuntive all'account di servizio dell'agente di servizio Cloud Healthcare. Per ulteriori informazioni, consulta Autorizzazioni Cloud Storage per gli archivi FHIR.

Generazione di dati simulati dei pazienti

Synthea™ è un simulatore per la generazione di dati sulla popolazione di pazienti. Se non utilizzi Synthea™ per generare dati sulla popolazione di pazienti, vai a Importazione delle risorse FHIR o Esportazione delle risorse FHIR.

Puoi importare i dati solo nella versione configurata per essere accettata dal tuo datastore FHIR.

Per scaricare e installare Synthea™:

  1. Clona il repository dello strumento Synthea™ da GitHub:

    git clone https://github.com/synthetichealth/synthea.git
    
  2. Completa i passaggi di installazione.

Vai a una delle seguenti sezioni per generare dati per una versione FHIR specifica:

Generazione di dati simulati dei pazienti per R4

Per impostazione predefinita, i dati di Synthea™ generati utilizzano la rappresentazione JSON FHIR R4 per le risorse. Per generare i dati Synthea™ FHIR R4 e importarli in un archivio FHIR dell'API Cloud Healthcare, segui questi passaggi:

  1. Segui le istruzioni per generare dati sintetici dei pazienti. I dati generati vengono visualizzati in synthea/output/fhir_r4 per FHIR R4.

  2. Copia i dati generati in un bucket Cloud Storage in modo da poterli importare in un archivio FHIR dell'API Cloud Healthcare. Ad esempio, per copiare i dati in una directory denominata synthea-data in un bucket Cloud Storage esistente, esegui il seguente comando gcloud storage cp dalla directory synthea:

    gcloud storage cp output/fhir_r4/* gs://BUCKET/synthea-data
  3. Segui le istruzioni per l'importazione delle risorse FHIR.

Generazione di dati simulati dei pazienti per DSTU2 o STU3

Per generare dati FHIR DSTU2 o STU3 di Synthea™ e importarli in un archivio FHIR dell'API Cloud Healthcare, segui questi passaggi:

  1. Dalla directory synthea, utilizza un editor di testo per aprire il file src/main/resources/synthea.properties e apporta le seguenti modifiche, a seconda che tu stia generando dati DSTU2 o STU3.

    Per generare dati FHIR STU3:

    • Imposta tutti i valori *.fhir.export e *.fhir_dstu2.export su false
    • Imposta tutti i valori *.fhir_stu3.export su true

    Per generare dati FHIR DSTU2:

    • Imposta tutti i valori *.fhir.export e *.fhir_stu3.export su false
    • Imposta tutti i valori *.fhir_dstu2.export su true

    Ad esempio, per generare dati FHIR STU3:

    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
  2. Segui le istruzioni per generare dati sintetici dei pazienti. I dati generati vengono visualizzati in synthea/output/fhir_stu3 per FHIR STU3 o nella directory synthea/output/fhir_dstu2 per FHIR DSTU2.

  3. Copia i dati generati in un bucket Cloud Storage in modo da poterli importare in un archivio FHIR dell'API Cloud Healthcare. Ad esempio, per copiare i dati in una directory denominata synthea-data in un bucket Cloud Storage esistente, esegui il seguente comando gcloud storage cp dalla directory synthea:

    gcloud storage cp output/fhir_stu3/* gs://BUCKET/synthea-data
  4. Segui le istruzioni per l'importazione delle risorse FHIR.

Importazione delle risorse FHIR

Quando configuri il corpo della richiesta di importazione, imposta ContentStructure su uno dei seguenti valori:

  • CONTENT_STRUCTURE_UNSPECIFIED
  • BUNDLE: il file di origine contiene una o più righe di JSON delimitato da nuova riga (ndjson). Ogni riga è un bundle che contiene una o più risorse. Se non specifichi ContentStructure, il valore predefinito è BUNDLE.
  • RESOURCE: il file di origine contiene una o più righe di JSON delimitato da nuova riga (ndjson). Ogni riga è una singola risorsa.
  • BUNDLE_PRETTY: l'intero file di origine è un bundle JSON. Il JSON può occupare più righe.
  • RESOURCE_PRETTY: l'intero file di origine è una risorsa JSON. Il JSON può essere su più righe.

Ad esempio, supponiamo di importare un file denominato resources.ndjson con il seguente contenuto:

{"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"}

Il file contiene due risorse Encounter e una risorsa Patient. Ogni risorsa è su una riga separata, quindi imposta ContentStructure su RESOURCE.

I dati potrebbero essere importati in modo errato o non essere importati affatto se ContentStructure non corrisponde al formato dei dati. Ad esempio, il file di esempio riportato sopra non verrà importato correttamente a meno che ContentStructure non sia impostato su RESOURCE nella richiesta di importazione.

Gli esempi riportati di seguito mostrano come importare le risorse FHIR da un bucket Cloud Storage.

Console

Per importare le risorse FHIR da un bucket Cloud Storage, completa i seguenti passaggi:

  1. Nella console Google Cloud, vai alla pagina Set di dati.
    Vai a Set di dati
  2. Fai clic sul set di dati contenente l'archivio FHIR in cui stai importando le risorse FHIR.
  3. Nell'elenco dei datastore, scegli Importa dall'elenco Azioni per l'archivio FHIR.

    Viene visualizzata la pagina Importa in archivio FHIR.
  4. Nell'elenco Progetto, seleziona un progetto Cloud Storage.
  5. Nell'elenco Posizione, seleziona un bucket Cloud Storage.
  6. In Impostazioni di importazione FHIR, seleziona la struttura dei contenuti pertinente.
  7. Fai clic su Importa per importare le risorse FHIR.
  8. Per monitorare lo stato dell'operazione, fai clic sulla scheda Operazioni. Al termine dell'operazione, vengono visualizzate le seguenti indicazioni:
    • La sezione Stato operazione a lunga esecuzione presenta un segno di spunta verde sotto la voce OK.
    • Nella sezione Panoramica è presente un segno di spunta verde e un indicatore OK nella stessa riga dell'ID operazione.
    In caso di errore, fai clic su Azioni e poi su Visualizza dettagli in Cloud Logging.

gcloud

Per importare risorse FHIR in un archivio FHIR, utilizza il comando gcloud healthcare fhir-stores import gcs. Specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • La posizione dell'oggetto in un bucket Cloud Storage. La posizione dei file nel bucket è arbitraria e non deve corrispondere esattamente al formato specificato nel seguente esempio. Al momento di specificare la posizione delle risorse FHIR in Cloud Storage, puoi utilizzare i caratteri jolly per importare più file da una o più directory. Sono supportati i seguenti caratteri jolly:
    • Utilizza * per trovare una corrispondenza con nessuno o più caratteri non separatori. Ad esempio, gs://BUCKET/DIRECTORY/Example*.ndjson corrisponde a Example.ndjson ed Example22.ndjson in DIRECTORY.
    • Utilizza ** per trovare una corrispondenza con nessuno o più caratteri (inclusi i separatori). Deve essere utilizzato alla fine di un percorso e senza altri caratteri jolly nel percorso. Può essere utilizzato anche con un'estensione di nome file (ad esempio .ndjson), che importa tutti i file con l'estensione di nome file nella directory specificata e nelle relative sottodirectory. Ad esempio, gs://BUCKET/DIRECTORY/**.ndjson importa tutti i file con l'estensione del nome file .ndjson in DIRECTORY e nelle relative sottodirectory.
    • Utilizza ? per trovare la corrispondenza di un solo carattere. Ad esempio, gs://BUCKET/DIRECTORY/Example?.ndjson corrisponde a Example1.ndjson, ma non a Example.ndjson o Example01.ndjson.

L'esempio seguente mostra il comando 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

Per specificare la struttura dei file di origine FHIR, utilizza il flag --content-structure.

La riga di comando mostra l'ID operazione e, al termine dell'operazione,done:

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

Per visualizzare ulteriori dettagli sull'operazione, esegui il comando gcloud healthcare operations describe fornendo il valore OPERATION_ID della risposta:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

La risposta include 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'
logsUrl: https://console.cloud.google.com/logs/query/CLOUD_LOGGING_URL,
counter:
  success: 'SUCCESS_COUNT' 
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

Per importare le risorse FHIR in un archivio FHIR, utilizza il metodo projects.locations.datasets.fhirStores.import.

  • La posizione dei file nel bucket è arbitraria e non deve necessariamente corrispondere esattamente al formato specificato nei seguenti esempi.
  • Al momento di specificare la posizione delle risorse FHIR in Cloud Storage, puoi utilizzare i caratteri jolly per importare più file da una o più directory. Sono supportati i seguenti caratteri jolly:
    • Utilizza * per trovare una corrispondenza con nessuno o più caratteri non separatori. Ad esempio, gs://BUCKET/DIRECTORY/Example*.ndjson corrisponde a Example.ndjson ed Example22.ndjson in DIRECTORY.
    • Utilizza ** per trovare una corrispondenza con nessuno o più caratteri (inclusi i separatori). Deve essere utilizzato alla fine di un percorso e senza altri caratteri jolly nel percorso. Può essere utilizzato anche con un'estensione di nome file (ad esempio .ndjson), che importa tutti i file con l'estensione di nome file nella directory specificata e nelle relative sottodirectory. Ad esempio, gs://BUCKET/DIRECTORY/**.ndjson importa tutti i file con l'estensione del nome file .ndjson in DIRECTORY e nelle relative sottodirectory.
    • Utilizza ? per trovare la corrispondenza di un solo carattere. Ad esempio, gs://BUCKET/DIRECTORY/Example?.ndjson corrisponde a Example1.ndjson, ma non a Example.ndjson o Example01.ndjson.

curl

Per importare risorse FHIR in un archivio FHIR, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • La posizione dell'oggetto in un bucket Cloud Storage
  • Un token di accesso

L'esempio seguente mostra come importare un singolo file utilizzando una richiesta POST con curl.

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"

Se la richiesta riesce, il server restituisce la risposta in formato JSON:

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

La risposta contiene il nome di un'operazione. Per monitorare lo stato dell'operazione, puoi utilizzare il metodo Operation get:

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"

Se la richiesta riesce, il server restituisce una risposta con lo stato dell'operazione in formato JSON:

{
  "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/query/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ImportResourcesResponse",
  }
}

PowerShell

Per importare risorse FHIR in un archivio FHIR, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • La posizione dell'oggetto in un bucket Cloud Storage
  • Un token di accesso

Il seguente esempio mostra una richiesta POST mediante 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

Se la richiesta riesce, il server restituisce la risposta in formato JSON:

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

La risposta contiene il nome di un'operazione. Per monitorare lo stato dell'operazione, puoi utilizzare il metodo Operation get:

$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

Se la richiesta riesce, il server restituisce una risposta con lo stato dell'operazione in formato JSON:

{
  "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/query/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: %w", 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: %w", 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.gson.GsonFactory;
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 GsonFactory();
  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/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

const importFhirResources = async () => {
  // 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, location, dataset_id, fhir_store_id, gcs_uri):
    """Import resources into the FHIR store by copying them from the
    specified source.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/fhir
    before running the sample."""
    # Imports the Google API Discovery Service.
    from googleapiclient import discovery

    api_version = "v1"
    service_name = "healthcare"
    # Instantiates an authorized API client by discovering the Healthcare API
    # and using GOOGLE_APPLICATION_CREDENTIALS environment variable.
    client = discovery.build(service_name, api_version)

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # fhir_store_id = 'my-fhir-store'  # replace with the FHIR store ID
    # gcs_uri = 'my-bucket'  # replace with a Cloud Storage bucket
    fhir_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, location, dataset_id
    )
    fhir_store_name = f"{fhir_store_parent}/fhirStores/{fhir_store_id}"

    body = {
        "contentStructure": "CONTENT_STRUCTURE_UNSPECIFIED",
        "gcsSource": {"uri": f"gs://{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(f"Imported FHIR resources: {gcs_uri}")

    return response

Esportazione delle risorse FHIR

Gli esempi riportati di seguito mostrano come esportare le risorse FHIR in un bucket Cloud Storage. Questa operazione prevede l'esportazione di tutte le risorse dell'archivio FHIR.

Se esporti le risorse FHIR in base a una pianificazione, ti consigliamo di esportare i dati in modo incrementale. Per istruzioni, consulta Esportazioni incrementali.

Durante l'esportazione, l'API Cloud Healthcare crea un file per ogni tipo di risorsa dall'archivio FHIR. Il nome del file è composto dall'ID operazione e dal tipo di risorsa separati da un trattino basso. Ogni file è costituito da un file JSON delimitato da nuova riga in cui ogni riga è una risorsa FHIR corrispondente al tipo di risorsa nel nome file. Ad esempio, se esporti più record di paziente, il file di output avrà un nome simile a 1264567891234567_Patient e conterrà una riga per ogni risorsa Patient dell'archivio FHIR.

Console

Per esportare le risorse FHIR in Cloud Storage, completa i seguenti passaggi:

  1. Nella console Google Cloud, vai alla pagina Set di dati.
    Vai a Set di dati
  2. Fai clic sul set di dati contenente l'archivio FHIR da cui stai esportando le risorse FHIR.
  3. Nell'elenco dei datastore, scegli Esporta dall'elenco Azioni per l'archivio FHIR.

    Viene visualizzata la pagina Esporta risorse FHIR.
  4. Seleziona Bucket Google Cloud Storage.
  5. Nell'elenco Progetto, seleziona un progetto Cloud Storage.
  6. Nell'elenco Posizione, seleziona un bucket Cloud Storage.
  7. Fai clic su Esporta per esportare le risorse FHIR nella posizione definita in Cloud Storage.
  8. Per monitorare lo stato dell'operazione, fai clic sulla scheda Operazioni. Al termine dell'operazione, vengono visualizzate le seguenti indicazioni:
    • La sezione Stato operazione a lunga esecuzione presenta un segno di spunta verde sotto la voce OK.
    • Nella sezione Panoramica è presente un segno di spunta verde e un indicatore OK nella stessa riga dell'ID operazione.
    In caso di errore, fai clic su Azioni e poi su Visualizza dettagli in Cloud Logging.

gcloud

Per esportare le risorse FHIR in un bucket Cloud Storage, utilizza il comando gcloud healthcare fhir-stores export gcs. Specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • Il nome del progetto principale
  • Il bucket o la directory Cloud Storage di destinazione. La scrittura deve avvenire in una directory o in un bucket Cloud Storage, anziché in un oggetto, perché l'API Cloud Healthcare crea un singolo oggetto per ciascun tipo di risorsa. Ogni oggetto è costituito da un file JSON delimitato da nuova riga in cui ogni riga è una risorsa FHIR. Se specifichi una directory che non esiste, verrà creata.
  • Un flag facoltativo, --resource-type, che esporta solo tipi di risorse specifici, definiti come un elenco separato da virgole di uno o più tipi di risorse FHIR
  • Un flag facoltativo, --since, che esporta solo le risorse aggiornate dopo un ora specifica, definita come YYYY-MM-DDThh:mm:ss.sss+zz:zz

L'esempio seguente mostra il comando gcloud healthcare fhir-stores export gcs.

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

La riga di comando mostra l'ID operazione:

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

Per visualizzare lo stato dell'operazione, esegui il comando gcloud healthcare operations describe fornendo il valore OPERATION_ID della risposta:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Al termine del comando, la risposta include 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

Per esportare le risorse FHIR, utilizza il metodo projects.locations.datasets.fhirStores.export.

  • La scrittura deve avvenire in una directory o in un bucket Cloud Storage, anziché in un oggetto, perché l'API Cloud Healthcare crea un singolo file JSON delimitato da nuova riga per ciascun tipo di risorsa. In ogni file JSON, ogni riga è una risorsa FHIR.
  • Se il comando specifica una directory non esistente, la directory viene creata.

curl

Per esportare le risorse FHIR, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • Il bucket Cloud Storage di destinazione
  • Un token di accesso
  • Un campo facoltativo, _type, che esporta solo tipi di risorse specifici, definiti come un elenco separato da virgole di uno o più tipi di risorse FHIR
  • Un campo facoltativo, _since, che esporta solo le risorse aggiornate dopo un ora specifica, definita come YYYY-MM-DDThh:mm:ss.sss+zz:zz

L'esempio seguente mostra una richiesta POST che utilizza 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"

Se la richiesta riesce, il server restituisce la risposta in formato JSON:

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

La risposta contiene il nome di un'operazione. Per monitorare lo stato dell'operazione, puoi utilizzare il metodo Operation get:

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"

Se la richiesta riesce, il server restituisce una risposta con lo stato dell'operazione in formato JSON:

{
  "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/query/CLOUD_LOGGING_URL",
    "counter": {
      "success": "SUCCESS_COUNT"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.fhir.rest.ExportResourcesResponse",
  }
}

PowerShell

Per esportare le risorse FHIR, effettua una richiesta POST e specifica le seguenti informazioni:

  • Il nome del set di dati principale
  • Il nome del datastore FHIR
  • Il bucket o la directory Cloud Storage di destinazione. La scrittura deve avvenire in una directory o in un bucket Cloud Storage, anziché in un oggetto, perché l'API Cloud Healthcare crea un singolo oggetto per ciascun tipo di risorsa. Ogni oggetto è costituito da un file JSON delimitato da nuova riga in cui ogni riga è una risorsa FHIR.
  • Un token di accesso
  • Un campo facoltativo, _type, che esporta solo tipi di risorse specifici, definiti come un elenco separato da virgole di uno o più tipi di risorse FHIR
  • Un campo facoltativo, _since, che esporta solo le risorse aggiornate dopo un ora specifica, definita come YYYY-MM-DDThh:mm:ss.sss+zz:zz

Il seguente esempio mostra una richiesta POST mediante 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

Se la richiesta riesce, il server restituisce la risposta in formato JSON:

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

La risposta contiene il nome di un'operazione. Per monitorare lo stato dell'operazione, puoi utilizzare il metodo Operation get:

$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

Se la richiesta riesce, il server restituisce una risposta con lo stato dell'operazione in formato JSON:

{
  "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/query/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: %w", 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: %w", 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.gson.GsonFactory;
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 GsonFactory();
  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/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

const exportFhirResourcesGcs = async () => {
  // 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, location, dataset_id, fhir_store_id, gcs_uri):
    """Export resources to a Google Cloud Storage bucket by copying
    them from the FHIR store.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/fhir
    before running the sample."""
    # Imports the Google API Discovery Service.
    from googleapiclient import discovery

    api_version = "v1"
    service_name = "healthcare"
    # Instantiates an authorized API client by discovering the Healthcare API
    # and using GOOGLE_APPLICATION_CREDENTIALS environment variable.
    client = discovery.build(service_name, api_version)

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # fhir_store_id = 'my-fhir-store' # replace with the FHIR store ID
    # gcs_uri = 'my-bucket' # replace with a Cloud Storage bucket
    fhir_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, location, dataset_id
    )
    fhir_store_name = f"{fhir_store_parent}/fhirStores/{fhir_store_id}"

    body = {"gcsDestination": {"uriPrefix": f"gs://{gcs_uri}/fhir_export"}}

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

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

    return response

Esportazioni incrementali

Puoi specificare un timestamp per esportare solo le risorse FHIR aggiunte al tuo datastore FHIR dopo un'esportazione riuscita precedente. In questo modo, vengono migliorate le prestazioni ed evitato il costo della re-esportazione dell'intero store FHIR, garantendo al contempo che i dati esportati siano sempre aggiornati.

Quando chiami fhirStores.export, specifica il timestamp nel campo _since.

Risolvere i problemi relativi alle richieste di importazione ed esportazione di FHIR

Se si verificano errori durante una richiesta di importazione o esportazione FHIR, questi vengono registrati in Cloud Logging. Per ulteriori informazioni, consulta Visualizzazione dei log degli errori in Cloud Logging.

Se l'intera operazione restituisce un errore, consulta la sezione Risoluzione dei problemi relativi alle operazioni a lunga esecuzione.

Passaggi successivi