Importe e exporte recursos FHIR através do Cloud Storage

Esta página explica como exportar e importar recursos FHIR para e a partir do Cloud Storage através dos métodos projects.locations.datasets.fhirStores.import e projects.locations.datasets.fhirStores.export.

Consoante o formato dos seus dados FHIR, para carregar dados para um arquivo FHIR, pode usar o método projects.locations.datasets.fhirStores.import ou o método projects.locations.datasets.fhirStores.fhir.executeBundle. Para orientações sobre a escolha de um método, consulte o artigo Importação de FHIR.

Definir autorizações do Cloud Storage

Antes de exportar e importar recursos FHIR para e a partir do Cloud Storage, tem de conceder autorizações adicionais à conta de serviço do agente do Cloud Healthcare Service . Para mais informações, consulte o artigo Autorizações do Cloud Storage da loja FHIR.

Gerar dados de pacientes simulados

O Synthea™ é um simulador para gerar dados da população de pacientes. Se não estiver a usar o Synthea™ para gerar dados da população de pacientes, avance para a secção Importar recursos FHIR ou Exportar recursos FHIR.

Só pode importar dados na versão que a sua loja FHIR está configurada para aceitar.

Para transferir e instalar o Synthea™, conclua os seguintes passos:

  1. Clone o repositório da ferramenta Synthea™ a partir do GitHub:

    git clone https://github.com/synthetichealth/synthea.git
    
  2. Conclua os passos de instalação.

Continue para uma das seguintes secções para gerar dados para uma versão específica da FHIR:

Gerar dados de pacientes simulados para o R4

Por predefinição, os dados Synthea™ gerados usam a representação JSON FHIR R4 para recursos. Para gerar dados FHIR R4 do Synthea™ e importá-los para um repositório FHIR da Cloud Healthcare API, conclua os seguintes passos:

  1. Siga as instruções para gerar dados sintéticos de pacientes. Os resultados de dados gerados são enviados para o synthea/output/fhir_r4 para FHIR R4.

  2. Copie os dados gerados para um contentor do Cloud Storage para que os possa importar para um arquivo FHIR da API Cloud Healthcare. Por exemplo, para copiar os dados para um diretório denominado synthea-data num contentor do Cloud Storage existente, execute o seguinte comando gcloud storage cp a partir do diretório synthea:

    gcloud storage cp output/fhir_r4/* gs://BUCKET/synthea-data
  3. Siga as instruções para importar recursos FHIR.

Gerar dados de pacientes simulados para DSTU2 ou STU3

Para gerar dados Synthea™ FHIR DSTU2 ou STU3 e importá-los para um repositório FHIR da Cloud Healthcare API, conclua os seguintes passos:

  1. No diretório synthea, use um editor de texto para abrir o ficheiro src/main/resources/synthea.properties e, em seguida, faça as seguintes alterações, consoante esteja a gerar dados DSTU2 ou STU3.

    Para gerar dados FHIR STU3:

    • Defina todos os valores de *.fhir.export e *.fhir_dstu2.export como false
    • Defina todos os valores de *.fhir_stu3.export como true

    Para gerar dados FHIR DSTU2:

    • Defina todos os valores de *.fhir.export e *.fhir_stu3.export como false
    • Defina todos os valores de *.fhir_dstu2.export como true

    Por exemplo, para gerar dados 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. Siga as instruções para gerar dados sintéticos de pacientes. Os dados gerados são enviados para o diretório synthea/output/fhir_stu3 para FHIR STU3 ou para o diretório synthea/output/fhir_dstu2 para FHIR DSTU2.

  3. Copie os dados gerados para um contentor do Cloud Storage para que os possa importar para um arquivo FHIR da API Cloud Healthcare. Por exemplo, para copiar os dados para um diretório denominado synthea-data num contentor do Cloud Storage existente, execute o seguinte comando gcloud storage cp a partir do diretório synthea:

    gcloud storage cp output/fhir_stu3/* gs://BUCKET/synthea-data
  4. Siga as instruções para importar recursos FHIR.

Importar recursos FHIR

Quando configurar o corpo do pedido de importação, defina o ContentStructure para um dos seguintes valores:

  • CONTENT_STRUCTURE_UNSPECIFIED
  • BUNDLE: o ficheiro de origem contém uma ou mais linhas de JSON delimitado por newline (ndjson). Cada linha é um pacote que contém um ou mais recursos. Se não especificar ContentStructure, a predefinição é BUNDLE.
  • RESOURCE: o ficheiro de origem contém uma ou mais linhas de JSON delimitado por newline (ndjson). Cada linha é um único recurso.
  • BUNDLE_PRETTY: todo o ficheiro de origem é um pacote JSON. O JSON pode abranger várias linhas.
  • RESOURCE_PRETTY: todo o ficheiro de origem é um recurso JSON. O JSON pode abranger várias linhas.

Por exemplo, suponha que está a importar um ficheiro denominado resources.ndjson com o seguinte conteúdo:

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

O ficheiro contém dois recursos Encounter e um recurso Patient. Cada recurso está numa linha separada, pelo que define ContentStructure como RESOURCE.

Os dados podem ser importados incorretamente ou não ser importados se ContentStructure não corresponderem ao formato dos dados. Por exemplo, o ficheiro de exemplo acima não é importado corretamente, a menos que ContentStructure esteja definido como RESOURCE no pedido de importação.

Os exemplos seguintes mostram como importar recursos FHIR de um contentor do Cloud Storage.

Consola

Para importar recursos FHIR de um contentor do Cloud Storage, conclua os seguintes passos:

  1. Na Google Cloud consola, aceda à página Conjuntos de dados.
    Aceder a conjuntos de dados
  2. Clique no conjunto de dados que contém o FHIR store para o qual está a importar recursos FHIR.
  3. Na lista de repositórios de dados, escolha Importar na lista Ações do repositório FHIR.

    É apresentada a página Importar para o repositório FHIR.
  4. Na lista Projeto, selecione um projeto do Cloud Storage.
  5. Na lista Localização, selecione um contentor do Cloud Storage.
  6. Em Definições de importação de FHIR, selecione a estrutura de conteúdo relevante.
  7. Clique em Importar para importar recursos FHIR.
  8. Para acompanhar o estado da operação, clique no separador Operações. Após a conclusão da operação, são apresentadas as seguintes indicações:
    • A secção Estado da operação de longa duração tem uma marca de verificação verde no cabeçalho OK.
    • A secção Vista geral tem uma marca de verificação verde e um indicador OK na mesma linha que o ID da operação.
    Se encontrar erros, clique em Ações e, de seguida, em Ver detalhes no Cloud Logging.

gcloud

Para importar recursos FHIR para uma loja FHIR, use o comando gcloud healthcare fhir-stores import gcs. Especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • A localização do objeto num contentor do Cloud Storage. A localização dos ficheiros no contentor é arbitrária e não tem de seguir exatamente o formato especificado no exemplo seguinte. Quando especifica a localização dos recursos FHIR no Cloud Storage, pode usar carateres universais para importar vários ficheiros de um ou mais diretórios. Os seguintes carateres universais são suportados:
    • Use * para corresponder a 0 ou mais carateres não separadores. Por exemplo, gs://BUCKET/DIRECTORY/Example*.ndjson corresponde a Example.ndjson e Example22.ndjson em DIRECTORY.
    • Use ** para representar 0 ou mais carateres (incluindo separadores). Tem de ser usado no final de um caminho e sem outros carateres universais no caminho. Também pode ser usado com uma extensão de nome de ficheiro (como .ndjson), que importa todos os ficheiros com a extensão de nome de ficheiro no diretório especificado e respetivos subdiretórios. Por exemplo, gs://BUCKET/DIRECTORY/**.ndjson importa todos os ficheiros com a extensão de nome de ficheiro .ndjson em DIRECTORY e nos respetivos subdiretórios.
    • Use ? para corresponder a 1 caráter. Por exemplo, gs://BUCKET/DIRECTORY/Example?.ndjson corresponde a Example1.ndjson, mas não corresponde a Example.ndjson nem a Example01.ndjson.

O exemplo seguinte mostra o 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

Para especificar a estrutura dos ficheiros de origem FHIR, use a flag --content-structure.

A linha de comandos apresenta o ID da operação e, após a conclusão da operação, 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

Para ver mais detalhes da operação, execute o comando gcloud healthcare operations describe e indique o OPERATION_ID da resposta:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

A resposta inclui 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

Para importar recursos FHIR para um arquivo FHIR, use o método projects.locations.datasets.fhirStores.import.

  • A localização dos ficheiros no segmento é arbitrária e não tem de seguir exatamente o formato especificado nos exemplos seguintes.
  • Quando especifica a localização dos recursos FHIR no Cloud Storage, pode usar carateres universais para importar vários ficheiros de um ou mais diretórios. Os seguintes carateres universais são suportados:
    • Use * para corresponder a 0 ou mais carateres não separadores. Por exemplo, gs://BUCKET/DIRECTORY/Example*.ndjson corresponde a Example.ndjson e Example22.ndjson em DIRECTORY.
    • Use ** para representar 0 ou mais carateres (incluindo separadores). Tem de ser usado no final de um caminho e sem outros carateres universais no caminho. Também pode ser usado com uma extensão de nome de ficheiro (como .ndjson), que importa todos os ficheiros com a extensão de nome de ficheiro no diretório especificado e respetivos subdiretórios. Por exemplo, gs://BUCKET/DIRECTORY/**.ndjson importa todos os ficheiros com a extensão de nome de ficheiro .ndjson em DIRECTORY e nos respetivos subdiretórios.
    • Use ? para corresponder a 1 caráter. Por exemplo, gs://BUCKET/DIRECTORY/Example?.ndjson corresponde a Example1.ndjson, mas não corresponde a Example.ndjson nem a Example01.ndjson.

curl

Para importar recursos FHIR para um arquivo FHIR, faça um pedido POST e especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • A localização do objeto num contentor do Cloud Storage
  • Uma chave de acesso

O exemplo seguinte mostra como importar um único ficheiro através de um pedido POST usando 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 o pedido for bem-sucedido, o servidor devolve a resposta no formato JSON:

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

A resposta contém um nome de operação. Para acompanhar o estado da operação, pode usar o método 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 o pedido for bem-sucedido, o servidor devolve uma resposta com o estado da operação no 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

Para importar recursos FHIR para um arquivo FHIR, faça um pedido POST e especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • A localização do objeto num contentor do Cloud Storage
  • Uma chave de acesso

O exemplo seguinte mostra um pedido POST através do 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 o pedido for bem-sucedido, o servidor devolve a resposta no formato JSON:

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

A resposta contém um nome de operação. Para acompanhar o estado da operação, pode usar o método 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 o pedido for bem-sucedido, o servidor devolve uma resposta com o estado da operação no 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

Exportar recursos FHIR

Os exemplos seguintes mostram como exportar recursos FHIR para um contentor do Cloud Storage. Quando exporta recursos FHIR de um FHIR store, todos os recursos no FHIR store são exportados.

Se exportar recursos FHIR de forma programada, considere exportar os dados de forma incremental. Para ver instruções, consulte o artigo Exportações incrementais.

Durante a exportação, a API Cloud Healthcare cria um ficheiro para cada tipo de recurso da loja FHIR. O nome do ficheiro é composto pelo ID da operação e pelo tipo de recurso separados por um sublinhado. Cada ficheiro consiste em JSON delimitado por novas linhas, em que cada linha é um recurso FHIR correspondente ao tipo de recurso no nome do ficheiro. Por exemplo, se exportar vários registos de pacientes, o ficheiro de saída vai ter um nome semelhante a 1264567891234567_Patient e vai conter uma linha para cada recurso de paciente da FHIR store.

Consola

Para exportar recursos FHIR para o Cloud Storage, conclua os seguintes passos:

  1. Na Google Cloud consola, aceda à página Conjuntos de dados.
    Aceder a conjuntos de dados
  2. Clique no conjunto de dados que contém o armazenamento FHIR a partir do qual está a exportar recursos FHIR.
  3. Na lista de arquivos de dados, escolha Exportar na lista Ações para o arquivo FHIR.

    É apresentada a página Exportar recursos FHIR.
  4. Selecione Contentor do Google Cloud Storage.
  5. Na lista Projeto, selecione um projeto do Cloud Storage.
  6. Na lista Localização, selecione um contentor do Cloud Storage.
  7. Clique em Exportar para exportar recursos FHIR para a localização definida no Cloud Storage.
  8. Para acompanhar o estado da operação, clique no separador Operações. Após a conclusão da operação, são apresentadas as seguintes indicações:
    • A secção Estado da operação de longa duração tem uma marca de verificação verde no cabeçalho OK.
    • A secção Vista geral tem uma marca de verificação verde e um indicador OK na mesma linha que o ID da operação.
    Se encontrar erros, clique em Ações e, de seguida, em Ver detalhes no Cloud Logging.

gcloud

Para exportar recursos FHIR para um contentor do Cloud Storage, use o comando gcloud healthcare fhir-stores export gcs. Especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • O nome do projeto principal
  • O contentor ou o diretório de destino do Cloud Storage. Escreva num diretório ou num contentor do Cloud Storage, em vez de num objeto, porque a Cloud Healthcare API cria um objeto para cada tipo de recurso. Cada objeto consiste em JSON delimitado por newline, em que cada linha é um recurso FHIR. Se especificar um diretório que não existe, este é criado.
  • Um parâmetro opcional, --resource-type, que exporta apenas tipos de recursos específicos, definidos como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR
  • Uma flag opcional, --since, que exporta apenas recursos atualizados após um momento específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

O exemplo seguinte mostra o 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

A linha de comandos apresenta o ID da operação:

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

Para ver o estado da operação, execute o comando gcloud healthcare operations describe e indique o OPERATION_ID da resposta:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Após a conclusão do comando, a resposta inclui 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

Para exportar recursos FHIR, use o método projects.locations.datasets.fhirStores.export.

  • Escreva num contentor ou diretório do Cloud Storage, em vez de num objeto, porque a Cloud Healthcare API cria um ficheiro JSON delimitado por nova linha para cada tipo de recurso. Em cada ficheiro JSON, cada linha é um recurso FHIR.
  • Se o comando especificar um diretório que não existe, o diretório é criado.

curl

Para exportar recursos FHIR, faça um pedido POST e especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • O contentor de destino do Cloud Storage
  • Uma chave de acesso
  • Um campo opcional, _type, que apenas exporta tipos de recursos específicos, definidos como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR
  • Um campo opcional, _since, que exporta apenas recursos atualizados após um momento específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

O exemplo seguinte mostra um pedido POST através de 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 o pedido for bem-sucedido, o servidor devolve a resposta no formato JSON:

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

A resposta contém um nome de operação. Para acompanhar o estado da operação, pode usar o método 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 o pedido for bem-sucedido, o servidor devolve uma resposta com o estado da operação no 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

Para exportar recursos FHIR, faça um pedido POST e especifique as seguintes informações:

  • O nome do conjunto de dados principal
  • O nome do FHIR store
  • O contentor ou o diretório de destino do Cloud Storage. Escreva num diretório ou num contentor do Cloud Storage, em vez de num objeto, porque a Cloud Healthcare API cria um objeto para cada tipo de recurso. Cada objeto consiste em JSON delimitado por newline, em que cada linha é um recurso FHIR.
  • Uma chave de acesso
  • Um campo opcional, _type, que apenas exporta tipos de recursos específicos, definidos como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR
  • Um campo opcional, _since, que exporta apenas recursos atualizados após um momento específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

O exemplo seguinte mostra um pedido POST através do 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 o pedido for bem-sucedido, o servidor devolve a resposta no formato JSON:

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

A resposta contém um nome de operação. Para acompanhar o estado da operação, pode usar o método 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 o pedido for bem-sucedido, o servidor devolve uma resposta com o estado da operação no 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

Exportações incrementais

Pode especificar uma data/hora para exportar apenas recursos FHIR adicionados à sua loja FHIR desde uma exportação bem-sucedida anterior. Isto melhora o desempenho e evita o custo de reexportar toda a loja FHIR, ao mesmo tempo que garante que os dados exportados estão sempre atualizados.

Quando chamar fhirStores.export, especifique a data/hora no campo _since.

Resolução de problemas de pedidos de importação e exportação de FHIR

Se ocorrerem erros durante um pedido de importação ou exportação de FHIR, os erros são registados no Cloud Logging. Para mais informações, consulte o artigo Ver registos de erros nos Registos na nuvem.

Se toda a operação devolver um erro, consulte o artigo Resolução de problemas de operações de longa duração.

O que se segue?