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, untuk memuat data ke dalam 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 Kesehatan Cloud. Untuk mengetahui informasi selengkapnya, lihat Izin Cloud Storage penyimpanan FHIR.

Membuat data pasien simulasi

Synthea™ adalah simulator untuk menghasilkan data populasi pasien. Jika Anda tidak menggunakan Synthea™ 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 Synthea™, selesaikan langkah-langkah berikut:

  1. Clone repositori alat Synthea™ dari GitHub:

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

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

Membuat data simulasi pasien untuk R4

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

  1. Ikuti petunjuk untuk membuat data pasien sintetis. Data yang dihasilkan akan menghasilkan output ke 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 ada, jalankan perintah gcloud storage cp berikut dari direktori synthea:

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

Membuat data simulasi pasien untuk DSTU2 atau STU3

Untuk membuat data Synthea™ FHIR DSTU2 atau STU3 dan mengimpornya ke dalam 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 membuat data DSTU2 atau STU3.

    Untuk membuat data FHIR STU3:

    • Menetapkan semua nilai *.fhir.export dan *.fhir_dstu2.export ke false
    • Menetapkan semua nilai *.fhir_stu3.export ke benar

    Untuk membuat data FHIR DSTU2:

    • Menetapkan semua nilai *.fhir.export dan *.fhir_stu3.export ke false
    • Menetapkan semua nilai *.fhir_dstu2.export ke benar

    Misalnya, untuk membuat 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. Output data yang dihasilkan ke 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 ada, jalankan perintah gcloud storage cp berikut dari direktori synthea:

    gcloud storage 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 yang dibatasi baris baru (ndjson). Setiap baris adalah paket, yang berisi satu atau beberapa resource. Jika Anda tidak menentukan ContentStructure, nilainya akan ditetapkan secara default ke BUNDLE.
  • RESOURCE: File sumber berisi satu atau beberapa baris JSON yang dibatasi baris baru (ndjson). Setiap baris adalah satu resource.
  • 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 ini berisi dua resource Encounter dan satu resource Pasien. Setiap resource berada di baris terpisah, sehingga Anda menetapkan ContentStructure ke RESOURCE.

Data Anda mungkin tidak diimpor dengan benar 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, selesaikan 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 Impor dari daftar Tindakan untuk penyimpanan FHIR.

    Halaman Impor ke penyimpanan FHIR 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 Impor untuk mengimpor resource FHIR.
  8. Untuk melacak status operasi, klik tab Operasi. Setelah operasi selesai, petunjuk berikut akan muncul:
    • Bagian Status operasi yang berjalan lama memiliki tanda centang hijau di bawah judul Oke.
    • Bagian Ringkasan memiliki tanda centang hijau dan indikator OK di baris yang sama dengan ID operasi.
    Jika Anda mengalami error, klik Actions, 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 penyimpanan FHIR
  • Lokasi objek di bucket Cloud Storage. Lokasi file dalam bucket bersifat arbitrer dan tidak harus mematuhi 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.
    • Gunakan ** untuk mencocokkan 0 atau beberapa karakter (termasuk pemisah). Harus digunakan di akhir jalur dan tanpa karakter pengganti lain 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 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 memberikan OPERATION_ID dari respons:

gcloud healthcare operations describe OPERATION_ID \
  --dataset=DATASET_ID

Responsnya 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 arbitrer dan tidak harus tepat mengikuti 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.
    • Gunakan ** untuk mencocokkan 0 atau beberapa karakter (termasuk pemisah). Harus digunakan di akhir jalur dan tanpa karakter pengganti lain 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 penyimpanan FHIR
  • Lokasi objek di 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 penyimpanan FHIR
  • Lokasi objek di 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.

Jika Anda mengekspor resource FHIR sesuai jadwal, pertimbangkan untuk mengekspor data secara bertahap. Untuk mengetahui petunjuknya, lihat Ekspor inkremental.

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 dipisahkan baris baru dengan setiap baris adalah resource FHIR yang sesuai dengan jenis resource dalam nama file. Misalnya, jika Anda mengekspor beberapa catatan Patient, file output akan diberi nama yang mirip dengan 1264567891234567_Patient dan akan berisi baris untuk setiap resource Patient 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 Ekspor dari daftar Tindakan untuk penyimpanan FHIR.

    Halaman Ekspor resource FHIR akan ditampilkan.
  4. Pilih Bucket Google Cloud Storage.
  5. Dalam daftar Project, pilih project Cloud Storage.
  6. Dalam daftar Location, pilih bucket Cloud Storage.
  7. Klik Ekspor untuk mengekspor resource FHIR ke lokasi yang ditentukan di Cloud Storage.
  8. Untuk melacak status operasi, klik tab Operasi. Setelah operasi selesai, petunjuk berikut akan muncul:
    • Bagian Status operasi yang berjalan lama memiliki tanda centang hijau di bawah judul Oke.
    • Bagian Ringkasan memiliki tanda centang hijau dan indikator OK di baris yang sama dengan ID operasi.
    Jika Anda mengalami error, klik Actions, 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 penyimpanan 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 dengan setiap barisnya adalah resource FHIR. Jika Anda menentukan direktori yang belum ada, direktori tersebut akan dibuat.
  • Flag opsional, --resource-type, yang hanya mengekspor jenis resource tertentu, yang ditentukan sebagai daftar yang dipisahkan koma dari satu atau beberapa jenis resource FHIR
  • Flag opsional, --since, yang hanya mengekspor resource yang diperbarui 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 akan 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 memberikan 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 dipisahkan baris baru untuk setiap jenis resource. Dalam setiap file JSON, setiap baris adalah resource FHIR.
  • Jika perintah menentukan direktori yang tidak ada, direktori akan dibuat.

curl

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

  • Nama set data induk
  • Nama penyimpanan FHIR
  • Bucket Cloud Storage tujuan
  • Token akses
  • Kolom opsional, _type, yang hanya mengekspor jenis resource tertentu, yang ditentukan sebagai daftar yang dipisahkan koma dari satu atau beberapa jenis resource FHIR
  • Kolom opsional, _since, yang hanya mengekspor resource yang diperbarui setelah waktu tertentu, yang ditentukan 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 penyimpanan 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 dipisahkan baris baru dengan setiap baris adalah resource FHIR.
  • Token akses
  • Kolom opsional, _type, yang hanya mengekspor jenis resource tertentu, yang ditentukan sebagai daftar yang dipisahkan koma dari satu atau beberapa jenis resource FHIR
  • Kolom opsional, _since, yang hanya mengekspor resource yang diperbarui setelah waktu tertentu, yang ditentukan 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

Ekspor inkremental

Anda dapat menentukan stempel waktu untuk hanya mengekspor resource FHIR yang ditambahkan ke penyimpanan FHIR sejak ekspor sebelumnya yang berhasil. Hal ini meningkatkan performa dan menghindari biaya ekspor ulang seluruh penyimpanan FHIR, sekaligus memastikan data yang diekspor selalu yang terbaru.

Saat memanggil fhirStores.export, tentukan stempel waktu di kolom _since.

Memecahkan masalah permintaan impor dan ekspor FHIR

Jika error terjadi selama permintaan impor atau ekspor FHIR, error tersebut akan dicatat ke log di Cloud Logging. Untuk mengetahui informasi selengkapnya, lihat artikel Melihat log error di Cloud Logging.

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

Langkah selanjutnya