Importar e exportar recursos FHIR com o Cloud Storage

Nesta página, explicamos como exportar e importar recursos do FHIR para e do Cloud Storage usando os métodos projects.locations.datasets.fhirStores.import e projects.locations.datasets.fhirStores.export.

Dependendo do formato dos dados do FHIR, para carregar dados em um armazenamento FHIR, use o método projects.locations.datasets.fhirStores.import ou projects.locations.datasets.fhirStores.fhir.executeBundle. Para orientações sobre como escolher um método, consulte Importação do FHIR.

Como definir permissões do Cloud Storage

Antes de exportar e importar recursos do FHIR de e para o Cloud Storage, é preciso conceder permissões adicionais à conta de serviço Agente de serviço do Cloud Healthcare. Para mais informações, consulte Permissões do Cloud Storage para armazenamento FHIR.

Como gerar dados simulados do paciente

O Synthea™ é um simulador para gerar dados de população de pacientes. Se você não estiver usando o Synthea™ para gerar dados populacionais de pacientes, pule para Como importar recursos FHIR ou Como exportar recursos FHIR.

Só é possível importar dados na versão que seu armazenamento FHIR está configurado para aceitar.

Para fazer o download e instalar o Synthea™, siga as seguintes etapas:

  1. Clone o repositório de ferramentas do Synthea™ do GitHub:

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

Continue para uma das seções a seguir para gerar dados de uma versão específica do FHIR:

Como gerar dados simulados do paciente para R4

Por padrão, os dados do Synthea™ gerados usam a representação FHIR R4 JSON para os recursos. Para gerar dados do FHIR R4 do Synthea™ e importá-los para um armazenamento de FHIR da API Cloud Healthcare, conclua as seguintes etapas:

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

  2. Copie os dados gerados para um bucket do Cloud Storage para importá-los para um armazenamento FHIR da API Cloud Healthcare. Por exemplo, para copiar os dados para um diretório chamado synthea-data em um bucket existente do Cloud Storage, execute o seguinte comando gcloud storage cp no diretório synthea:

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

Como gerar dados simulados de pacientes para DSTU2 ou STU3

Para gerar dados de FHIR da DSTU2 ou STU3 do Synthea™ e importá-los para um armazenamento de FHIR da API Cloud Healthcare, conclua as seguintes etapas:

  1. No diretório synthea, use um editor de texto para abrir o arquivo src/main/resources/synthea.properties e depois faça as seguintes alterações, dependendo se você está gerando dados do DSTU2 ou do STU3.

    Para gerar dados do FHIR STU3:

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

    Para gerar dados do FHIR DSTU2:

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

    Por exemplo, para gerar dados do 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 synthea/output/fhir_stu3 para o FHIR STU3 ou para o diretório synthea/output/fhir_dstu2 para o FHIR DSTU2.

  3. Copie os dados gerados para um bucket do Cloud Storage para importá-los para um armazenamento FHIR da API Cloud Healthcare. Por exemplo, para copiar os dados para um diretório chamado synthea-data em um bucket existente do Cloud Storage, execute o seguinte comando gcloud storage cp no diretório synthea:

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

Como importar recursos para o FHIR

Ao configurar o corpo da solicitação de importação, defina ContentStructure como um dos seguintes valores:

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

Por exemplo, suponha que você esteja importando um arquivo chamado 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 arquivo contém dois recursos do Encounter e um recurso Paciente. Como cada recurso está em uma linha separada, você define ContentStructure como RESOURCE.

Seus dados poderão ser importados incorretamente ou não serão importados se ContentStructure não corresponder ao formato dos dados. Por exemplo, o arquivo de amostra acima não será importado corretamente, a menos que ContentStructure seja definido como RESOURCE na solicitação de importação.

Os exemplos a seguir mostram como importar recursos de um bucket do Cloud Storage para o FHIR.

Console

Para importar recursos FHIR de um bucket do Cloud Storage, conclua estas etapas:

  1. No console do Google Cloud, acesse a página Conjuntos de dados.
    Acessar a página Conjuntos de dados
  2. Clique no conjunto de dados em que está o armazenamento de FHIR para que você está importando recursos de FHIR.
  3. Na lista de armazenamentos de dados, escolhaImportação na lista de Ações para o armazenamento de FHIR.

    A página Importar para o armazenamento de FHIR é exibida.
  4. Na lista Projeto, selecione um projeto do Cloud Storage.
  5. Na lista Local, selecione um bucket do Cloud Storage.
  6. Em Configurações de importação do FHIR, selecione a estrutura do conteúdo relevante.
  7. Clique em Importar para importar recursos FHIR.
  8. Para acompanhar o status da operação, clique na guia Operações. Após a conclusão da operação, as seguintes indicações serão exibidas:
    • A seção Status da operação de longa duração tem uma marca de seleção verde no cabeçalho OK.
    • A seção Visão geral tem uma marca de seleção verde e um indicador OK na mesma linha do ID da operação.
    Se você encontrar erros, clique em Ações e depois em Ver detalhes no Cloud Logging.

gcloud

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

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O local do objeto em um bucket do Cloud Storage. O local dos arquivos no bucket é arbitrário e não precisa aderir exatamente ao formato especificado na amostra a seguir. Ao especificar o local dos recursos do FHIR no Cloud Storage, você pode usar caracteres curinga para importar vários arquivos de um ou mais diretórios. Os seguintes caracteres curinga são suportados:
    • Use * para corresponder a 0 ou mais caracteres que não sejam separadores. Por exemplo, gs://BUCKET/DIRECTORY/Example*.ndjson corresponde a Example.ndjson e Example22.ndjson em DIRECTORY.
    • Use ** para corresponder a 0 ou mais caracteres (incluindo separadores). Precisa ser usado no final de um caminho e sem outros caracteres curinga no caminho. Também pode ser usado com uma extensão de nome de arquivo (como .ndjson), que importa todos os arquivos com a extensão de nome de arquivo no diretório especificado e seus subdiretórios. Por exemplo, gs://BUCKET/DIRECTORY/**.ndjson importa todos os arquivos com a extensão de nome de arquivo .ndjson em DIRECTORY e seus subdiretórios.
    • Use ? para corresponder a um caractere. Por exemplo, gs://BUCKET/DIRECTORY/Example?.ndjson corresponde a Example1.ndjson, mas não corresponde a Example.ndjson nem Example01.ndjson.

A amostra a seguir exibe 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 arquivos de origem do FHIR, use a flag --content-structure.

A linha de comando exibe 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, fornecendo 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 do FHIR para um armazenamento FHIR, use o método projects.locations.datasets.fhirStores.import.

  • O local dos arquivos no bucket é arbitrário e não precisa aderir exatamente ao formato especificado nas amostras a seguir.
  • Ao especificar o local dos recursos do FHIR no Cloud Storage, você pode usar caracteres curinga para importar vários arquivos de um ou mais diretórios. Os seguintes caracteres curinga são suportados:
    • Use * para corresponder a 0 ou mais caracteres que não sejam separadores. Por exemplo, gs://BUCKET/DIRECTORY/Example*.ndjson corresponde a Example.ndjson e Example22.ndjson em DIRECTORY.
    • Use ** para corresponder a 0 ou mais caracteres (incluindo separadores). Precisa ser usado no final de um caminho e sem outros caracteres curinga no caminho. Também pode ser usado com uma extensão de nome de arquivo (como .ndjson), que importa todos os arquivos com a extensão de nome de arquivo no diretório especificado e seus subdiretórios. Por exemplo, gs://BUCKET/DIRECTORY/**.ndjson importa todos os arquivos com a extensão de nome de arquivo .ndjson em DIRECTORY e seus subdiretórios.
    • Use ? para corresponder a um caractere. Por exemplo, gs://BUCKET/DIRECTORY/Example?.ndjson corresponde a Example1.ndjson, mas não corresponde a Example.ndjson nem Example01.ndjson.

curl

Para importar recursos do FHIR para um armazenamento FHIR, faça uma solicitação POST e especifique as seguintes informações:

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O local do objeto em um bucket do Cloud Storage
  • Um token de acesso

O exemplo a seguir mostra como importar um único arquivo usando uma solicitação 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 a solicitação for bem-sucedida, o servidor retornará 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 rastrear o status da operação, use o método get de operação:

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 a solicitação for bem-sucedida, o servidor retornará uma resposta com o status 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 do FHIR para um armazenamento FHIR, faça uma solicitação POST e especifique as seguintes informações:

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O local do objeto em um bucket do Cloud Storage
  • Um token de acesso

O exemplo a seguir mostra uma solicitação POST usando o 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 a solicitação for bem-sucedida, o servidor retornará 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 rastrear o status da operação, use o método get de operação:

$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 a solicitação for bem-sucedida, o servidor retornará uma resposta com o status 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

Como exportar recursos do FHIR

Os exemplos a seguir mostram como exportar recursos do FHIR para um bucket do Cloud Storage. Quando você exporta recursos do FHIR de um armazenamento FHIR, todos os recursos no armazenamento FHIR são exportados.

Se você exporta recursos do FHIR em uma programação, exporte seus dados de forma incremental. Para instruções, consulte Exportações incrementais.

Durante a exportação, a API Cloud Healthcare cria um arquivo para cada tipo de recurso do armazenamento de FHIR. O nome do arquivo consiste no ID da operação e no tipo de recurso, separados por um sublinhado. Cada arquivo consiste em JSON delimitado por nova linha, em que uma linha é um recurso FHIR correspondente ao tipo de recurso no nome de arquivo. Por exemplo, se você exportar vários registros de paciente, o arquivo de saída terá um nome semelhante a 1264567891234567_Patient e conterá uma linha para cada recurso paciente do armazenamento de FHIR.

Console

Para exportar recursos FHIR para o Cloud Storage, conclua as seguintes etapas:

  1. No console do Google Cloud, acesse a página Conjuntos de dados.
    Acessar a página Conjuntos de dados
  2. Clique no conjunto de dados em que está o armazenamento de FHIR de que você está exportando recursos de FHIR.
  3. Na lista de armazenamentos de dados, escolha Exportar na lista Ações para o armazenamento de FHIR.

    Os recursos de exportação de FHIR são exibidos.
  4. Selecione Bucket do Google Cloud Storage.
  5. Na lista Projeto, selecione um projeto do Cloud Storage.
  6. Na lista Local, selecione um bucket do Cloud Storage.
  7. Clique em Exportar para exportar recursos FHIR para o local definido no Cloud Storage.
  8. Para acompanhar o status da operação, clique na guia Operações. Após a conclusão da operação, as seguintes indicações serão exibidas:
    • A seção Status da operação de longa duração tem uma marca de seleção verde no cabeçalho OK.
    • A seção Visão geral tem uma marca de seleção verde e um indicador OK na mesma linha do ID da operação.
    Se você encontrar erros, clique em Ações e depois em Ver detalhes no Cloud Logging.

gcloud

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

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O nome do projeto pai
  • O bucket ou diretório de destino do Cloud Storage. Grave em um bucket ou diretório do Cloud Storage, em vez de um objeto, porque a API Cloud Healthcare cria um objeto para cada tipo de recurso. Cada objeto consiste em JSON delimitado por nova linha, em que cada linha é um recurso do FHIR. Se você especificar um diretório que não existe, ele será criado.
  • Uma flag opcional, --resource-type, que exporta apenas tipos de recurso específicos, definidos como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR.
  • Uma flag opcional, --since, que só exporta recursos atualizados após um horário específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

A amostra a seguir exibe 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 comando exibe 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 status da operação, execute o comando gcloud healthcare operations describe, fornecendo o OPERATION_ID da resposta:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Depois que o comando for concluído, a resposta incluirá 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 do FHIR, use o método projects.locations.datasets.fhirStores.export.

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

curl

Para exportar recursos do FHIR, faça uma solicitação POST e especifique as seguintes informações:

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O bucket de destino do Cloud Storage
  • Um token de acesso
  • Um campo opcional, _type, que exporta apenas tipos de recursos específicos, definido como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR.
  • Um campo opcional, _since, que só exporta recursos atualizados após um horário específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

O exemplo a seguir mostra uma solicitação 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 "{
      'gcsDestination': {
        'uriPrefix': 'gs://BUCKET/DIRECTORY'
      },
    }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:export"

Se a solicitação for bem-sucedida, o servidor retornará 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 rastrear o status da operação, use o método get de operação:

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 a solicitação for bem-sucedida, o servidor retornará uma resposta com o status 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 do FHIR, faça uma solicitação POST e especifique as seguintes informações:

  • O nome do conjunto de dados pai
  • O nome do armazenamento FHIR
  • O bucket ou diretório de destino do Cloud Storage. Grave em um bucket ou diretório do Cloud Storage, em vez de um objeto, porque a API Cloud Healthcare cria um objeto para cada tipo de recurso. Cada objeto consiste em JSON delimitado por nova linha, em que cada linha é um recurso do FHIR.
  • Um token de acesso
  • Um campo opcional, _type, que exporta apenas tipos de recursos específicos, definido como uma lista separada por vírgulas de um ou mais tipos de recursos FHIR.
  • Um campo opcional, _since, que só exporta recursos atualizados após um horário específico, definido como YYYY-MM-DDThh:mm:ss.sss+zz:zz

O exemplo a seguir mostra uma solicitação POST usando o 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 a solicitação for bem-sucedida, o servidor retornará 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 rastrear o status da operação, use o método get de operação:

$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 a solicitação for bem-sucedida, o servidor retornará uma resposta com o status 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

É possível especificar um carimbo de data/hora para exportar apenas os recursos do FHIR adicionados ao armazenamento de FHIR desde uma exportação anterior. Isso melhora o desempenho e evita o custo de exportar novamente toda a loja FHIR, além de garantir que os dados exportados estejam sempre atualizados.

Ao chamar fhirStores.export, especifique o carimbo de data/hora no campo _since.

Solução de problemas de solicitações de importação e exportação do FHIR

Se ocorrerem erros durante uma solicitação de importação ou exportação do FHIR, eles serão registrados no Cloud Logging. Para mais informações, consulte Como visualizar registros de erros no Cloud Logging.

Se toda a operação retornar um erro, consulte Como solucionar problemas de operações de longa duração.

A seguir