Mengimpor dan mengekspor resource FHIR menggunakan Cloud Storage

Halaman ini menjelaskan cara mengekspor dan mengimpor resource FHIR ke dan dari Cloud Storage menggunakan metode projects.locations.datasets.fhirStores.import dan projects.locations.datasets.fhirStores.export.

Bergantung pada format data FHIR Anda, untuk memuat data ke penyimpanan FHIR, Anda dapat menggunakan metode projects.locations.datasets.fhirStores.import atau metode projects.locations.datasets.fhirStores.fhir.executeBundle. Untuk panduan dalam memilih metode, lihat impor FHIR.

Menetapkan izin Cloud Storage

Sebelum mengekspor dan mengimpor resource FHIR ke dan dari Cloud Storage, Anda harus memberikan izin tambahan ke akun layanan Agen Layanan Cloud Healthcare. Untuk mengetahui informasi selengkapnya, lihat izin Cloud Storage penyimpanan FHIR.

Membuat data simulasi pasien

SyntheaTM adalah simulator untuk menghasilkan data populasi pasien. Jika Anda tidak menggunakan SyntheaTM untuk menghasilkan data populasi pasien, lanjutkan ke Mengimpor resource FHIR atau Mengekspor resource FHIR.

Anda hanya dapat mengimpor data dalam versi yang dikonfigurasi untuk diterima oleh penyimpanan FHIR Anda.

Untuk mendownload dan menginstal SyntheaTM, selesaikan langkah-langkah berikut:

  1. Clone repositori alat SyntheaTM dari GitHub:

    git clone https://github.com/synthetichealth/synthea.git
    
  2. Selesaikan langkah-langkah penginstalan.

Lanjutkan ke salah satu bagian berikut guna menghasilkan data untuk versi FHIR tertentu:

Membuat simulasi data pasien untuk R4

Secara default, data SyntheaTM yang dihasilkan menggunakan representasi JSON FHIR R4 untuk resource. Untuk membuat data SyntheaTM FHIR R4 dan mengimpornya ke penyimpanan FHIR Cloud Healthcare API, selesaikan langkah-langkah berikut:

  1. Ikuti petunjuk untuk membuat data pasien sintetis. Data yang dihasilkan akan menghasilkan synthea/output/fhir_r4 untuk FHIR R4.

  2. Salin data yang dihasilkan ke bucket Cloud Storage sehingga Anda dapat mengimpornya ke penyimpanan FHIR Cloud Healthcare API. Misalnya, untuk menyalin data ke direktori bernama synthea-data di bucket Cloud Storage yang sudah ada, jalankan perintah gsutil cp berikut dari direktori synthea:

    gsutil -m cp output/fhir_r4/* gs://BUCKET/synthea-data
    
  3. Ikuti petunjuk untuk mengimpor resource FHIR.

Menghasilkan data pasien simulasi untuk DSTU2 atau STU3

Untuk membuat data SyntheaTM FHIR DSTU2 atau STU3 dan mengimpornya ke penyimpanan FHIR Cloud Healthcare API, selesaikan langkah-langkah berikut:

  1. Dari direktori synthea, gunakan editor teks untuk membuka file src/main/resources/synthea.properties, lalu buat perubahan berikut, bergantung pada apakah Anda menghasilkan data DSTU2 atau STU3.

    Untuk menghasilkan data FHIR STU3:

    • Tetapkan semua nilai *.fhir.export dan *.fhir_dstu2.export ke false
    • Tetapkan semua nilai *.fhir_stu3.export ke benar (true)

    Untuk membuat data FHIR DSTU2:

    • Tetapkan semua nilai *.fhir.export dan *.fhir_stu3.export ke false
    • Tetapkan semua nilai *.fhir_dstu2.export ke benar (true)

    Misalnya, untuk menghasilkan data 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. Ikuti petunjuk untuk membuat data pasien sintetis. Data yang dihasilkan akan menghasilkan synthea/output/fhir_stu3 untuk FHIR STU3 atau direktori synthea/output/fhir_dstu2 untuk FHIR DSTU2.

  3. Salin data yang dihasilkan ke bucket Cloud Storage sehingga Anda dapat mengimpornya ke penyimpanan FHIR Cloud Healthcare API. Misalnya, untuk menyalin data ke direktori bernama synthea-data di bucket Cloud Storage yang sudah ada, jalankan perintah gsutil cp berikut dari direktori synthea:

    gsutil -m cp output/fhir_stu3/* gs://BUCKET/synthea-data
    
  4. Ikuti petunjuk untuk mengimpor resource FHIR.

Mengimpor resource FHIR

Saat mengonfigurasi isi permintaan impor, tetapkan ContentStructure ke salah satu nilai berikut:

  • CONTENT_STRUCTURE_UNSPECIFIED
  • BUNDLE: File sumber berisi satu atau beberapa baris JSON (ndjson) yang dibatasi baris baru. Setiap baris adalah paket, yang berisi satu atau beberapa resource. Jika Anda tidak menentukan ContentStructure, nilai defaultnya adalah BUNDLE.
  • RESOURCE: File sumber berisi satu atau beberapa baris JSON yang dibatasi baris baru (ndjson). Setiap baris adalah resource tunggal.
  • BUNDLE_PRETTY: Seluruh file sumber adalah satu paket JSON. JSON dapat mencakup beberapa baris.
  • RESOURCE_PRETTY: Seluruh file sumber adalah satu resource JSON. JSON dapat mencakup beberapa baris.

Misalnya, Anda mengimpor file bernama resources.ndjson dengan konten berikut:

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

File berisi dua resource Meetup dan satu resource Pasien. Setiap resource berada di baris terpisah sehingga Anda menyetel ContentStructure ke RESOURCE.

Data Anda mungkin salah diimpor atau tidak diimpor sama sekali jika ContentStructure tidak cocok dengan format data Anda. Misalnya, file contoh di atas tidak akan diimpor dengan benar kecuali jika ContentStructure ditetapkan ke RESOURCE dalam permintaan impor.

Contoh berikut menunjukkan cara mengimpor resource FHIR dari bucket Cloud Storage.

Konsol

Untuk mengimpor resource FHIR dari bucket Cloud Storage, lakukan langkah-langkah berikut:

  1. Di konsol Google Cloud, buka halaman Datasets.
    Buka Datasets
  2. Klik set data yang berisi penyimpanan FHIR tempat Anda mengimpor resource FHIR.
  3. Dalam daftar penyimpanan data, pilih Import dari daftar Actions untuk penyimpanan FHIR.

    Halaman Import to FHIR store akan muncul.
  4. Dalam daftar Project, pilih project Cloud Storage.
  5. Dalam daftar Location, pilih bucket Cloud Storage.
  6. Di FHIR import settings, pilih struktur konten yang relevan.
  7. Klik Import untuk mengimpor resource FHIR.
  8. Untuk melacak status operasi, klik tab Operasi. Setelah operasi selesai, indikasi berikut akan muncul:
    • Bagian Long-running Operations status memiliki tanda centang hijau di bawah heading OK.
    • Bagian Overview memiliki tanda centang hijau dan indikator OK di baris yang sama dengan ID operasi.
    Jika Anda mengalami error, klik Tindakan, lalu klik View details in Cloud Logging.

gcloud

Untuk mengimpor resource FHIR ke penyimpanan FHIR, gunakan perintah gcloud healthcare fhir-stores import gcs. Tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Lokasi objek dalam bucket Cloud Storage. Lokasi file dalam bucket bersifat tidak tentu dan tidak harus mematuhi secara persis format yang ditentukan dalam contoh berikut. Saat menentukan lokasi resource FHIR di Cloud Storage, Anda dapat menggunakan karakter pengganti untuk mengimpor beberapa file dari satu atau beberapa direktori. Karakter pengganti berikut didukung:
    • Gunakan * untuk mencocokkan 0 atau beberapa karakter nonpemisah. Misalnya, gs://BUCKET/DIRECTORY/Example*.ndjson cocok dengan Example.ndjson dan Example22.ndjson di DIRECTORY.
    • Menggunakan ** untuk mencocokkan 0 atau beberapa karakter (termasuk pemisah). Harus digunakan di akhir jalur dan tanpa karakter pengganti lainnya di jalur. Dapat juga digunakan dengan ekstensi nama file (seperti .ndjson), yang mengimpor semua file dengan ekstensi nama file di direktori yang ditentukan dan subdirektorinya. Misalnya, gs://BUCKET/DIRECTORY/**.ndjson mengimpor semua file dengan ekstensi nama file .ndjson di DIRECTORY dan subdirektorinya.
    • Gunakan ? untuk mencocokkan 1 karakter. Misalnya, gs://BUCKET/DIRECTORY/Example?.ndjson cocok dengan Example1.ndjson, tetapi tidak cocok dengan Example.ndjson atau Example01.ndjson.

Contoh berikut menunjukkan perintah 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

Untuk menentukan struktur file sumber FHIR, gunakan flag --content-structure.

Command line akan menampilkan ID operasi dan, setelah operasi selesai, 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

Untuk melihat detail operasi selengkapnya, jalankan perintah gcloud healthcare operations describe, yang menyediakan OPERATION_ID dari respons:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Respons menyertakan 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

Untuk mengimpor resource FHIR ke penyimpanan FHIR, gunakan metode projects.locations.datasets.fhirStores.import.

  • Lokasi file dalam bucket bersifat tidak tentu dan tidak harus mematuhi secara persis format yang ditentukan dalam contoh berikut.
  • Saat menentukan lokasi resource FHIR di Cloud Storage, Anda dapat menggunakan karakter pengganti untuk mengimpor beberapa file dari satu atau beberapa direktori. Karakter pengganti berikut didukung:
    • Gunakan * untuk mencocokkan 0 atau beberapa karakter nonpemisah. Misalnya, gs://BUCKET/DIRECTORY/Example*.ndjson cocok dengan Example.ndjson dan Example22.ndjson di DIRECTORY.
    • Menggunakan ** untuk mencocokkan 0 atau beberapa karakter (termasuk pemisah). Harus digunakan di akhir jalur dan tanpa karakter pengganti lainnya di jalur. Dapat juga digunakan dengan ekstensi nama file (seperti .ndjson), yang mengimpor semua file dengan ekstensi nama file di direktori yang ditentukan dan subdirektorinya. Misalnya, gs://BUCKET/DIRECTORY/**.ndjson mengimpor semua file dengan ekstensi nama file .ndjson di DIRECTORY dan subdirektorinya.
    • Gunakan ? untuk mencocokkan 1 karakter. Misalnya, gs://BUCKET/DIRECTORY/Example?.ndjson cocok dengan Example1.ndjson, tetapi tidak cocok dengan Example.ndjson atau Example01.ndjson.

curl

Untuk mengimpor resource FHIR ke penyimpanan FHIR, buat permintaan POST dan tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Lokasi objek dalam bucket Cloud Storage
  • Token akses

Contoh berikut menunjukkan cara mengimpor satu file menggunakan permintaan POST menggunakan 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"

Jika permintaan berhasil, server akan menampilkan respons dalam format JSON:

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

Respons berisi nama operasi. Untuk melacak status operasi, Anda dapat menggunakan metode get Operasi:

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"

Jika permintaan berhasil, server akan menampilkan respons dengan status operasi dalam format 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

Untuk mengimpor resource FHIR ke penyimpanan FHIR, buat permintaan POST dan tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Lokasi objek dalam bucket Cloud Storage
  • Token akses

Contoh berikut menunjukkan permintaan POST menggunakan 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

Jika permintaan berhasil, server akan menampilkan respons dalam format JSON:

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

Respons berisi nama operasi. Untuk melacak status operasi, Anda dapat menggunakan metode get Operasi:

$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

Jika permintaan berhasil, server akan menampilkan respons dengan status operasi dalam format 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

Mengekspor resource FHIR

Contoh berikut menunjukkan cara mengekspor resource FHIR ke bucket Cloud Storage. Saat Anda mengekspor resource FHIR dari penyimpanan FHIR, semua resource di penyimpanan FHIR akan diekspor.

Selama ekspor, Cloud Healthcare API membuat satu file untuk setiap jenis resource dari penyimpanan FHIR. Nama file terdiri dari ID operasi dan jenis resource yang dipisahkan dengan garis bawah. Setiap file terdiri dari JSON yang dibatasi baris baru, dan setiap barisnya adalah resource FHIR yang sesuai dengan jenis resource dalam nama file. Misalnya, jika Anda mengekspor beberapa data Pasien, file output akan bernama sesuatu yang mirip dengan 1264567891234567_Patient dan akan berisi satu baris untuk setiap resource Pasien dari penyimpanan FHIR.

Konsol

Untuk mengekspor resource FHIR ke Cloud Storage, selesaikan langkah-langkah berikut:

  1. Di konsol Google Cloud, buka halaman Datasets.
    Buka Datasets
  2. Klik set data yang berisi penyimpanan FHIR tempat Anda mengekspor resource FHIR.
  3. Dalam daftar penyimpanan data, pilih Export dari daftar Actions untuk penyimpanan FHIR.

    Halaman Export FHIR resources akan ditampilkan.
  4. Pilih Google Cloud Storage Bucket.
  5. Dalam daftar Project, pilih project Cloud Storage.
  6. Dalam daftar Location, pilih bucket Cloud Storage.
  7. Klik Export untuk mengekspor resource FHIR ke lokasi yang ditentukan di Cloud Storage.
  8. Untuk melacak status operasi, klik tab Operasi. Setelah operasi selesai, indikasi berikut akan muncul:
    • Bagian Long-running Operations status memiliki tanda centang hijau di bawah heading OK.
    • Bagian Overview memiliki tanda centang hijau dan indikator OK di baris yang sama dengan ID operasi.
    Jika Anda mengalami error, klik Tindakan, lalu klik View details in Cloud Logging.

gcloud

Untuk mengekspor resource FHIR ke bucket Cloud Storage, gunakan perintah gcloud healthcare fhir-stores export gcs. Tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Nama project induk
  • Bucket atau direktori Cloud Storage tujuan. Tulis ke bucket atau direktori Cloud Storage, bukan objek, karena Cloud Healthcare API membuat satu objek untuk setiap jenis resource. Setiap objek terdiri dari JSON yang dibatasi baris baru, dan setiap barisnya merupakan resource FHIR. Jika Anda menentukan direktori yang tidak ada, direktori tersebut akan dibuat.
  • Flag opsional, --resource-type, yang hanya mengekspor jenis resource tertentu, yang didefinisikan sebagai daftar yang dipisahkan koma yang berisi satu atau beberapa jenis resource FHIR
  • Tanda opsional, --since, yang hanya mengekspor resource yang diupdate setelah waktu tertentu, yang ditentukan sebagai YYYY-MM-DDThh:mm:ss.sss+zz:zz

Contoh berikut menunjukkan perintah 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

Command line menampilkan ID operasi:

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

Untuk melihat status operasi, jalankan perintah gcloud healthcare operations describe, yang menyediakan OPERATION_ID dari respons:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Setelah perintah selesai, respons akan menyertakan 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

Untuk mengekspor resource FHIR, gunakan metode projects.locations.datasets.fhirStores.export.

  • Tulis ke bucket atau direktori Cloud Storage, bukan objek, karena Cloud Healthcare API membuat satu file JSON yang dibatasi baris baru untuk setiap jenis resource. Di setiap file JSON, setiap baris adalah resource FHIR.
  • Jika perintah tersebut menentukan direktori yang tidak ada, direktori tersebut akan dibuat.

curl

Untuk mengekspor resource FHIR, buat permintaan POST dan tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Bucket Cloud Storage tujuan
  • Token akses
  • Kolom opsional, _type, yang hanya mengekspor jenis resource tertentu, ditetapkan sebagai daftar yang dipisahkan koma yang berisi satu atau beberapa jenis resource FHIR
  • Kolom opsional, _since, yang hanya mengekspor resource yang diupdate setelah waktu tertentu, yang ditetapkan sebagai YYYY-MM-DDThh:mm:ss.sss+zz:zz

Contoh berikut menunjukkan permintaan POST yang menggunakan 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"

Jika permintaan berhasil, server akan menampilkan respons dalam format JSON:

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

Respons berisi nama operasi. Untuk melacak status operasi, Anda dapat menggunakan metode get Operasi:

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"

Jika permintaan berhasil, server akan menampilkan respons dengan status operasi dalam format 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

Untuk mengekspor resource FHIR, buat permintaan POST dan tentukan informasi berikut:

  • Nama set data induk
  • Nama toko FHIR
  • Bucket atau direktori Cloud Storage tujuan. Tulis ke bucket atau direktori Cloud Storage, bukan objek, karena Cloud Healthcare API membuat satu objek untuk setiap jenis resource. Setiap objek terdiri dari JSON yang dibatasi baris baru, dengan setiap barisnya merupakan resource FHIR.
  • Token akses
  • Kolom opsional, _type, yang hanya mengekspor jenis resource tertentu, ditetapkan sebagai daftar yang dipisahkan koma yang berisi satu atau beberapa jenis resource FHIR
  • Kolom opsional, _since, yang hanya mengekspor resource yang diupdate setelah waktu tertentu, yang ditetapkan sebagai YYYY-MM-DDThh:mm:ss.sss+zz:zz

Contoh berikut menunjukkan permintaan POST menggunakan 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

Jika permintaan berhasil, server akan menampilkan respons dalam format JSON:

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

Respons berisi nama operasi. Untuk melacak status operasi, Anda dapat menggunakan metode get Operasi:

$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

Jika permintaan berhasil, server akan menampilkan respons dengan status operasi dalam format 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

Memecahkan masalah permintaan impor dan ekspor FHIR

Jika terjadi error selama permintaan impor atau ekspor FHIR, error tersebut akan dicatat ke dalam log ke Cloud Logging. Untuk mengetahui informasi lebih lanjut, baca bagian Melihat log error di Cloud Logging.

Jika seluruh operasi menampilkan error, lihat Memecahkan masalah operasi yang berjalan lama.

Langkah selanjutnya