FHIR 리소스 검색

이 페이지에서는 FHIR 저장소에서 FHIR 리소스를 검색하는 방법에 대한 기본 안내를 제공합니다. FHIR 리소스 검색은 FHIR 데이터를 쿼리하고 통계를 얻기 위한 기본 방법입니다.

다음 방식으로 Cloud Healthcare API에서 FHIR 리소스를 검색할 수 있습니다.

이 페이지에서 일반적으로 사용되는 여러 기능을 요약해서 보여주지만, 이 목록은 Cloud Healthcare API로 지원되는 FHIR 검색 사양의 전체 목록이 아닙니다.

FHIR 뷰어 사용

FHIR 뷰어는 FHIR 리소스의 콘텐츠를 검색하고 볼 수 있는 Google Cloud Console의 페이지입니다.

FHIR 저장소의 리소스를 검색하려면 다음 단계를 완료하세요.

  1. Google Cloud 콘솔에서 FHIR 뷰어 페이지로 이동합니다.

    FHIR 뷰어로 이동

  2. FHIR 저장소 드롭다운 목록에서 데이터 세트를 선택한 다음 데이터 세트의 FHIR 저장소를 선택합니다.

  3. 리소스 유형 목록을 필터링하려면 표시할 리소스 유형을 검색하세요.

    1. 리소스 유형 필드를 클릭합니다.

    2. 표시되는 속성 드롭다운 목록에서 리소스 유형을 선택합니다.

    3. 리소스 유형을 입력합니다.

    4. 다른 리소스 유형을 검색하려면 표시되는 연산자 드롭다운 목록에서 OR을 선택한 후 다른 리소스 유형을 입력하세요.

  4. 리소스 유형 목록에서 검색할 리소스 유형을 선택합니다.

  5. 표시되는 리소스 테이블의 검색창에 검색할 값을 입력합니다.

FHIR 뷰어는 테이블에 검색결과를 표시합니다. 리소스를 선택하면 FHIR 뷰어에 리소스의 콘텐츠가 표시됩니다.

리소스의 콘텐츠를 보는 경우 리소스 내의 데이터를 검색할 수 있습니다.

리소스 내에서 데이터를 검색하려면 다음 단계별 안내를 따르세요.

  1. 리소스를 선택하세요.

  2. FHIR 뷰어 창에서 요소 탭을 클릭합니다.

  3. 검색창에 검색하려는 값을 입력합니다.

FHIR 리소스 내에서 바이너리 데이터 다운로드

FHIR 뷰어에서 리소스와 연관된 사용 가능한 바이너리 데이터를 다운로드하려면 다음 단계를 수행하세요.

  1. 리소스를 선택하세요.

  2. FHIR 뷰어 창에서 요소 탭을 클릭합니다.

  3. 필요에 따라 요소를 확장하여 필요한 리소스 요소에 액세스합니다.

  4. 파일 다운로드를 클릭하여 사용 가능한 데이터를 다운로드합니다.

고급 검색어 만들기 및 실행

고급 검색어를 사용하면 FHIR 검색 사양을 통해 특정 FHIR 리소스를 검색할 수 있습니다.

고급 검색어를 만들려면 다음 단계를 완료하세요.

  1. FHIR 뷰어 페이지에서 검색 탭을 클릭합니다.

  2. 검색어를 만들려면 쿼리 빌더 열기를 클릭합니다.

    쿼리 선택 패널이 표시됩니다.

  3. FHIR 리소스 유형 선택 목록에서 검색할 FHIR 리소스 유형을 선택합니다.

  4. 계속을 클릭합니다.

  5. 매개변수 목록에서 리소스를 검색하는 데 사용할 매개변수를 선택합니다.

  6. 한정자 목록에서 쿼리에 적용할 한정자를 선택합니다. 이 목록에는 선택한 매개변수의 데이터 유형과 호환되는 한정자만 포함됩니다.

    이 옵션은 선택사항입니다. 한정자를 선택하지 않으면 동등성 검사가 수행됩니다.

  7. 필드에 쿼리 매개변수의 값을 입력합니다.

  8. 매개변수 값을 두 개 이상 추가하려면 OR을 클릭합니다. 이렇게 하면 검색어에 리소스 매개변수 값을 여러 개 포함할 수 있습니다.

    작성 중인 검색어가 쿼리 미리보기 창에 표시됩니다. 검색어의 전체 URL을 보려면 전체 경로 표시를 클릭합니다.

  9. 매개변수를 두 개 이상 추가하려면 AND를 클릭합니다.

  10. 계속을 클릭합니다.

  11. 반환된 리소스가 참조하는 리소스를 검색어에 포함하려면 포함된 매개변수 드롭다운 목록에서 리소스 매개변수를 선택합니다.

  12. 반환된 리소스를 참조하는 리소스를 검색어에 포함하려면 역포함된 매개변수 드롭다운 목록에서 리소스 매개변수를 선택합니다.

  13. 완료를 클릭하여 검색어를 저장합니다.

    저장된 검색어가 FHIR 검색 작업 필드에 표시됩니다.

  14. 쿼리로 리소스를 검색하려면 검색 실행을 클릭합니다.

    검색 결과가 검색 결과 목록에 표시됩니다. 검색에서 반환한 리소스의 세부정보를 보려면 목록에서 리소스를 클릭합니다.

  15. 쿼리를 쿼리 템플릿으로 저장하려면 템플릿 저장을 클릭하고 템플릿 저장이나 템플릿을 다른 이름으로 저장을 선택합니다. 쿼리의 이름과 설명을 입력하라는 메시지가 표시됩니다. 쿼리 매개변수는 템플릿에 저장되지만 정의된 값은 삭제됩니다.

검색어 예시

다음 예시는 Practitioner/12345라는 특정 의료인의 2021년 8월에 해당하는 클레임 리소스를 검색하는 검색어입니다.

  • 매개변수: care-team
    • : Practitioner/12345
  • 연산자: AND
  • 매개변수: created
    • 프리픽스: lt (lesser than)
    • : 8/1/21, 12:00 AM
  • 연산자: AND
  • 매개변수: created
    • 프리픽스: gt (greater than)
    • : 8/31/21, 11:59 PM

이는 쿼리 선택 패널에서 다음과 같이 구성되며 쿼리가 쿼리 미리보기 창에 미리 표시됩니다. FHIR 검색 작업 필드에 쿼리가 표시됩니다.

FHIR 고급 검색어

검색어 수정

검색어를 수정하려면 다음 중 하나를 수행하세요.

  • 쿼리 빌더에서 쿼리를 수정하려면 쿼리 빌더 열기를 클릭합니다.
  • 쿼리를 수동으로 수정하려면 텍스트 상자에서 매개변수 값을 수정합니다.

쿼리 템플릿 실행

저장된 템플릿에서 쿼리를 실행하려면 다음 단계를 완료하세요.

  1. 저장된 템플릿을 클릭합니다.

    쿼리 선택 패널의 템플릿 검색 탭이 표시되고 저장된 모든 쿼리 템플릿이 표시됩니다.

  2. 실행할 쿼리 템플릿을 선택하고 완료를 클릭합니다.

    템플릿의 검색어가 FHIR 검색 작업 필드에 값 없이 표시됩니다.

  3. 검색어의 값을 정의하려면 필드에서 매개변수 값을 수정하세요.

  4. 검색 실행을 클릭하여 쿼리로 리소스를 검색합니다.

search 메서드 사용

REST API를 사용하여 FHIR 리소스를 검색하려면 projects.locations.datasets.fhirStores.fhir.search 메서드를 사용합니다. GET 또는 POST 요청을 사용하여 메서드를 호출할 수 있습니다.

GET에서 search 메서드 사용

다음 샘플은 GET으로 projects.locations.datasets.fhirStores.fhir.search 메서드를 사용해서 지정된 FHIR 저장소에서 리소스를 검색하는 방법을 보여줍니다.

curl

FHIR 저장소의 리소스를 검색하려면 GET 요청을 수행하고 다음 정보를 지정합니다.

  • 데이터 세트의 이름
  • FHIR 저장소의 이름
  • 검색할 리소스 유형
  • 검색 쿼리 구성하기 섹션에 설명된 대로 검색중인 정보가 포함된 쿼리 문자열
  • 액세스 토큰

다음 샘플은 성이 'Smith'인 모든 환자를 검색하기 위해 curl을 사용하는 GET 요청을 보여줍니다.

curl -X GET \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient?family:exact=Smith"

요청이 성공하면 서버가 JSON 형식의 FHIR Bundle로 응답을 반환합니다. Bundle.typesearchset이며 검색 결과는 Bundle.entry 배열의 항목입니다. 이 예시에서 요청은 해당 리소스 내의 데이터가 포함된 단일 환자 리소스를 반환합니다.

{
  "entry": [
    {
      "fullUrl": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID",
      "resource": {
        "birthDate": "1970-01-01",
        "gender": "female",
        "id": "PATIENT_ID",
        "meta": {
          "lastUpdated": "LAST_UPDATED",
          "versionId": "VERSION_ID"
        },
        "name": [
          {
            "family": "Smith",
            "given": [
              "Darcy"
            ],
            "use": "official"
          }
        ],
        "resourceType": "Patient"
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": [
    {
      "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/?family%3Aexact=Smith"
    }
  ],
  "resourceType": "Bundle",
  "total": 1,
  "type": "searchset"
}

PowerShell

FHIR 저장소의 리소스를 검색하려면 GET 요청을 수행하고 다음 정보를 지정합니다.

  • 데이터 세트의 이름
  • FHIR 저장소의 이름
  • 검색할 리소스 유형
  • 검색 쿼리 구성하기 섹션에 설명된 대로 검색중인 정보가 포함된 쿼리 문자열
  • 액세스 토큰

다음 샘플은 성이 'Smith'인 모든 환자를 검색하기 위해 Windows PowerShell을 사용하는 GET 요청을 보여줍니다.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-RestMethod `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/RESOURCE_TYPE?family:exact=Smith" | ConvertTo-Json

요청이 성공하면 서버가 JSON 형식의 FHIR Bundle로 응답을 반환합니다. Bundle.typesearchset이며 검색 결과는 Bundle.entry 배열의 항목입니다. 이 예시에서 요청은 해당 리소스 내의 데이터가 포함된 단일 환자 리소스를 반환합니다.

{
  "entry": [
    {
      "fullUrl": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID",
      "resource": {
        "birthDate": "1970-01-01",
        "gender": "female",
        "id": "PATIENT_ID",
        "meta": {
          "lastUpdated": "LAST_UPDATED",
          "versionId": "VERSION_ID"
        },
        "name": [
          {
            "family": "Smith",
            "given": [
              "Darcy"
            ],
            "use": "official"
          }
        ],
        "resourceType": "Patient"
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": [
    {
      "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/?family%3Aexact=Smith"
    }
  ],
  "resourceType": "Bundle",
  "total": 1,
  "type": "searchset"
}

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.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;

public class FhirResourceSearchGet {
  private static final String FHIR_NAME =
      "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s";
  // The endpoint URL for the Healthcare API. Required for HttpClient.
  private static final String API_ENDPOINT = "https://healthcare.googleapis.com";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void fhirResourceSearchGet(String resourceName)
      throws IOException, URISyntaxException {
    // String resourceName =
    //    String.format(
    //        FHIR_NAME, "project-id", "region-id", "dataset-id", "fhir-store-id");
    // String resourceType = "Patient";

    // Instantiate the client, which will be used to interact with the service.
    HttpClient httpClient = HttpClients.createDefault();
    String uri = String.format("%s/v1/%s", API_ENDPOINT, resourceName);
    URIBuilder uriBuilder = new URIBuilder(uri).setParameter("access_token", getAccessToken());
    // To set additional parameters for search filtering, add them to the URIBuilder. For
    // example, to search for a Patient with the family name "Smith", specify the following:
    // uriBuilder.setParameter("family:exact", "Smith");

    HttpUriRequest request =
        RequestBuilder.get()
            .setUri(uriBuilder.build())
            .build();

    // Execute the request and process the results.
    HttpResponse response = httpClient.execute(request);
    HttpEntity responseEntity = response.getEntity();
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      System.err.print(
          String.format(
              "Exception searching GET FHIR resources: %s\n", response.getStatusLine().toString()));
      responseEntity.writeTo(System.err);
      throw new RuntimeException();
    }
    System.out.println("FHIR resource GET search results: ");
    responseEntity.writeTo(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();
  }

  private static String getAccessToken() throws IOException {
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    return credential.refreshAccessToken().getTokenValue();
  }
}

Node.js

// Import google-auth-library for authentication.
const {GoogleAuth} = require('google-auth-library');

const searchFhirResourcesGet = async () => {
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/cloud-platform',
  });
  // 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 resourceType = 'Patient';
  const url = `https://healthcare.googleapis.com/v1/projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}`;

  const params = {};
  // Specify search filters in a params object. For example, to filter on a
  // Patient with the last name "Smith", set resourceType to "Patient" and
  // specify the following params:
  // params = {'family:exact' : 'Smith'};
  const client = await auth.getClient();
  const response = await client.request({url, method: 'GET', params});
  const resources = response.data.entry;
  console.log(`Resources found: ${resources.length}`);
  console.log(JSON.stringify(resources, null, 2));
};

searchFhirResourcesGet();

Python

def search_resources_get(
    project_id,
    location,
    dataset_id,
    fhir_store_id,
    resource_type,
):
    """
    Uses the searchResources GET method to search for resources in the given FHIR store.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/fhir
    before running the sample."""
    # Imports Python's built-in "os" module
    import os

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using a service account
    from google.oauth2 import service_account

    # Gets credentials from the environment.
    credentials = service_account.Credentials.from_service_account_file(
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
    )
    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # 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
    # resource_type = 'Patient'  # replace with the FHIR resource type
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    resource_path = "{}/datasets/{}/fhirStores/{}/fhir/{}".format(
        url, dataset_id, fhir_store_id, resource_type
    )

    response = session.get(resource_path)
    response.raise_for_status()

    resources = response.json()

    print(
        "Using GET request, found a total of {} {} resources:".format(
            resources["total"], resource_type
        )
    )
    print(json.dumps(resources, indent=2))

    return resources

POST에서 search 메서드 사용

다음 샘플은 POST으로 projects.locations.datasets.fhirStores.fhir.search 메서드를 사용해서 지정된 FHIR 저장소에서 리소스를 검색하는 방법을 보여줍니다.

curl

FHIR 저장소의 리소스를 검색하려면 POST 요청을 수행하고 다음 정보를 지정합니다.

  • 데이터 세트의 이름
  • FHIR 저장소의 이름
  • 검색할 리소스 유형
  • 검색 쿼리 구성하기 섹션에 설명된 대로 검색중인 정보가 포함된 쿼리 문자열
  • 액세스 토큰

다음 샘플은 성이 'Smith'인 모든 환자를 검색하기 위해 curl을 사용하는 POST 요청을 보여줍니다.

curl -X POST \
    --data "" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/fhir+json; charset=utf-8" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/_search?family:exact=Smith"

요청이 성공하면 서버가 JSON 형식의 FHIR Bundle로 응답을 반환합니다. Bundle.typesearchset이며 검색 결과는 Bundle.entry 배열의 항목입니다. 이 예시에서 요청은 해당 리소스 내의 데이터가 포함된 단일 환자 리소스를 반환합니다.

{
  "entry": [
    {
      "fullUrl": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID",
      "resource": {
        "birthDate": "1970-01-01",
        "gender": "female",
        "id": "PATIENT_ID",
        "meta": {
          "lastUpdated": "LAST_UPDATED",
          "versionId": "VERSION_ID"
        },
        "name": [
          {
            "family": "Smith",
            "given": [
              "Darcy"
            ],
            "use": "official"
          }
        ],
        "resourceType": "Patient"
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": [
    {
      "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/?family%3Aexact=Smith"
    }
  ],
  "resourceType": "Bundle",
  "total": 1,
  "type": "searchset"
}

PowerShell

FHIR 저장소의 리소스를 검색하려면 POST 요청을 수행하고 다음 정보를 지정합니다.

  • 데이터 세트의 이름
  • FHIR 저장소의 이름
  • 검색할 리소스 유형
  • 검색 쿼리 구성하기 섹션에 설명된 대로 검색중인 정보가 포함된 쿼리 문자열
  • 액세스 토큰

다음 샘플은 성이 'Smith'인 모든 환자를 검색하기 위해 Windows PowerShell을 사용하는 POST 요청을 보여줍니다.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred" }

Invoke-RestMethod `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/fhir+json; charset=utf-8" `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/_search?family:exact=Smith" | ConvertTo-Json

요청이 성공하면 서버가 JSON 형식의 FHIR Bundle로 응답을 반환합니다. Bundle.typesearchset이며 검색 결과는 Bundle.entry 배열의 항목입니다. 이 예시에서 요청은 해당 리소스 내의 데이터가 포함된 단일 환자 리소스를 반환합니다.

{
  "entry": [
    {
      "fullUrl": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID",
      "resource": {
        "birthDate": "1970-01-01",
        "gender": "female",
        "id": "PATIENT_ID",
        "meta": {
          "lastUpdated": "LAST_UPDATED",
          "versionId": "VERSION_ID"
        },
        "name": [
          {
            "family": "Smith",
            "given": [
              "Darcy"
            ],
            "use": "official"
          }
        ],
        "resourceType": "Patient"
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": [
    {
      "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/?family%3Aexact=Smith"
    }
  ],
  "resourceType": "Bundle",
  "total": 1,
  "type": "searchset"
}

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.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;

public class FhirResourceSearchPost {
  private static final String FHIR_NAME =
      "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s";
  // The endpoint URL for the Healthcare API. Required for HttpClient.
  private static final String API_ENDPOINT = "https://healthcare.googleapis.com";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void fhirResourceSearchPost(String resourceName)
      throws IOException, URISyntaxException {
    // String resourceName =
    //    String.format(
    //        FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "resource-type");

    // Instantiate the client, which will be used to interact with the service.
    HttpClient httpClient = HttpClients.createDefault();
    String uri = String.format("%s/v1/%s/_search", API_ENDPOINT, resourceName);
    URIBuilder uriBuilder = new URIBuilder(uri).setParameter("access_token", getAccessToken());
    // To set additional parameters for search filtering, add them to the URIBuilder. For
    // example, to search for a Patient with the family name "Smith", specify the following:
    // uriBuilder.setParameter("family:exact", "Smith");

    // Set a body otherwise HttpClient complains there is no Content-Length set.
    StringEntity requestEntity = new StringEntity("");

    HttpUriRequest request =
        RequestBuilder.post()
            .setUri(uriBuilder.build())
            .setEntity(requestEntity)
            .addHeader("Content-Type", "application/fhir+json")
            .addHeader("Accept-Charset", "utf-8")
            .addHeader("Accept", "application/fhir+json; charset=utf-8")
            .build();

    // Execute the request and process the results.
    HttpResponse response = httpClient.execute(request);
    HttpEntity responseEntity = response.getEntity();
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      System.err.print(
          String.format(
              "Exception searching POST FHIR resources: %s\n",
              response.getStatusLine().toString()));
      responseEntity.writeTo(System.err);
      throw new RuntimeException();
    }
    System.out.println("FHIR resource POST search results: ");
    responseEntity.writeTo(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();
  }

  private static String getAccessToken() throws IOException {
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    return credential.refreshAccessToken().getTokenValue();
  }
}

Node.js

// Import google-auth-library for authentication.
const {GoogleAuth} = require('google-auth-library');

const searchFhirResourcesPost = async () => {
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/cloud-platform',
    // Set application/fhir+json header because this is a POST request.
    headers: {'Content-Type': 'application/fhir+json'},
  });
  // 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 resourceType = 'Patient';
  const url = `https://healthcare.googleapis.com/v1/projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}/_search`;

  const params = {};
  // Specify search filters in a params object. For example, to filter on a
  // Patient with the last name "Smith", set resourceType to "Patient" and
  // specify the following params:
  // params = {'family:exact' : 'Smith'};
  const client = await auth.getClient();
  const response = await client.request({url, method: 'POST', params});
  const resources = response.data.entry;
  console.log(`Resources found: ${resources.length}`);
  console.log(JSON.stringify(resources, null, 2));
};

searchFhirResourcesPost();

Python

def search_resources_post(project_id, location, dataset_id, fhir_store_id):
    """
    Searches for resources in the given FHIR store. Uses the
    _search POST method and a query string containing the
    information to search for. In this sample, the search criteria is
    'family:exact=Smith' on a Patient resource.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/fhir
    before running the sample."""
    # Imports Python's built-in "os" module
    import os

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using a service account
    from google.oauth2 import service_account

    # Gets credentials from the environment.
    credentials = service_account.Credentials.from_service_account_file(
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
    )
    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # 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
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    fhir_store_path = "{}/datasets/{}/fhirStores/{}/fhir".format(
        url, dataset_id, fhir_store_id
    )

    resource_path = f"{fhir_store_path}/Patient/_search?family:exact=Smith"

    # Sets required application/fhir+json header on the request
    headers = {"Content-Type": "application/fhir+json;charset=utf-8"}

    response = session.post(resource_path, headers=headers)
    response.raise_for_status()

    resources = response.json()
    print(
        "Using POST request, found a total of {} Patient resources:".format(
            resources["total"]
        )
    )

    print(json.dumps(resources, indent=2))

    return resources

검색어 구성하기

쿼리 문자열은 URL 형식으로 인코딩된 일련의 name=value 쌍입니다. 검색은 모든 쌍을 논리 AND로 조합합니다. 각 값은 쉼표로 구분된 값 목록일 수 있으며, 해당 값의 논리 OR로 취급됩니다. 예를 들어 Patient?key1=value1&key2=value2,value3은 다음 기준을 사용하여 환자 리소스를 검색합니다.

(key1 = value1) AND (key2 = value2 OR key2 = value3)

name=value 쌍의 OR을 수행하는 구문은 없습니다.

각 FHIR 리소스 유형은 FHIR의 각 버전에서 고유한 검색 매개변수를 정의합니다. 사용 가능한 매개변수는 각 리소스의 FHIR 사양에 기술되어 있습니다. 예를 보려면 FHIR R4 환자를 참조하세요. 기능 문을 통해 프로그래매틱 방식으로 매개변수를 검색할 수 있습니다. Cloud Healthcare API는 대부분의 검색 매개변수를 지원합니다. 기능 문 또는 FHIR 적합성 명세를 통해 제외 항목을 찾을 수 있습니다.

페이지로 나누기 및 정렬

FHIR 검색결과의 각 페이지에서 반환되는 리소스 수는 다음 요소에 따라 달라집니다.

  • _count 매개변수. 검색 메서드에서 반환되는 최대 리소스 수를 제어합니다. 예를 들어 _count=10은 쿼리와 일치하는 리소스를 최대 10개 반환합니다. 기본값은 100이고 허용되는 최댓값은 1,000입니다.
  • 응답 데이터의 크기. 응답 크기가 크면 검색결과 페이지가 _count 매개변수에 지정된 값보다 적은 리소스를 반환할 수 있습니다.

검색으로 한 페이지에 들어가는 리소스 수보다 많은 리소스가 반환되면 응답의 Bundle.link 필드에 페이지로 나누기 URL이 포함됩니다. 이 필드에는 여러 값이 반환될 수 있습니다. Bundle.link.relation = next가 있는 값은 해당 Bundle.link.url을 사용하여 다음 페이지를 검색할 수 있음을 나타냅니다.

Bundle.total 값은 일치하는 리소스의 총 개수를 나타냅니다. 결과가 온전히 한 페이지에 맞을 경우 이 값은 정확하지만 결과의 수가 한 페이지보다 많아지면 추정치가 됩니다. 결과가 소진될 때까지 페이지로 나누기 링크를 반복적으로 따라가면 많은 결과와 일치하는 검색의 정확한 합계를 얻을 수 있습니다.

페이지로 나누기 및 검색 합계에 대한 자세한 내용은 FHIR 검색을 사용하여 페이지로 나누기 및 검색 합계 구현을 참조하세요.

쉼표로 구분된 검색 매개변수 이름 목록을 우선순위로 허용하는 _sort 매개변수를 사용하여 결과를 정렬할 수 있습니다. - 프리픽스를 사용하여 감소 순서를 나타낼 수 있습니다. 예를 들어 다음 쿼리는 상태 오름차순, 날짜 내림차순에 따른 동점차순, 카테고리 오름차순에 따른 나머지 동점차순에 따라 정렬합니다.

_sort=status,-date,category

색인 생성 지연

FHIR 리소스에서 비동기적으로 색인이 생성되므로 리소스가 생성되거나 변경되는 시점과 변경사항이 검색결과에 반영되는 시점 사이에 약간의 지연이 있을 수 있습니다. 유일한 예외는 리소스 식별자 데이터로서, 특정 색인으로 색인이 동기적으로 생성됩니다. 따라서 리소스 식별자를 사용하여 검색하면 색인 생성 지연이 발생하지 않습니다. 특수 동기 색인을 사용하려면 식별자 검색어가 identifier=[system]|[value] 또는 identifier=[value] 패턴에 있어야 합니다. 그러면 다음과 같은 검색 결과 매개변수를 사용할 수 있습니다.

  • _count
  • _include
  • _revinclude
  • _summary
  • _elements

쿼리에 다른 검색 매개변수가 포함된 경우에는 표준 비동기 색인이 대신 사용됩니다. 특수 색인에 대한 검색은 소수의 일치 항목을 확인하는 데 최적화되어 있습니다. 식별자 검색 기준이 다수의 리소스(예: 2,000개 초과)와 일치하는 경우 검색은 최적화되지 않습니다. 다수의 리소스와 일치하는 검색어의 경우 쿼리에 추가 _sort 매개변수를 포함하여 특수 동기 색인을 사용하지 않을 수 있습니다. 기본 정렬 순서를 유지하려면 _sort=-_lastUpdated를 사용합니다.

모든 리소스 유형에서 검색

_id와 같은 선행 밑줄로 표시되는 특정 검색 매개변수는 모든 리소스 유형에 적용됩니다. 이러한 모든 리소스 매개변수는 리소스 유형의 FHIR 사양에 나열됩니다.

이러한 검색 매개변수를 사용할 때 요청 경로에서 리소스 유형을 생략하여 여러 리소스 유형을 검색할 수 있습니다. 예를 들어 환자 리소스만이 아니라 모든 FHIR 리소스에서 GET .../fhir/Patient?_id=1234 대신 GET .../fhir?_id=1234를 사용합니다. 이 유형의 요청과 함께 특수 매개변수 _type을 사용하여 결과를 쉼표로 구분된 리소스 유형 목록으로 제한할 수 있습니다. 예를 들어 다음 쿼리는 ObservationCondition 리소스에 대해 일치하는 결과만 반환합니다.

GET .../fhir?_tag=active&_type=Observation,Condition

데이터 유형

FHIR에 의해 정의된 각 검색 매개변수에는 다음과 같은 기본 유형이 있는 데이터 유형이 있습니다.

  • 문자열
  • 숫자
  • 날짜

데이터 유형에는 다음과 같은 복잡한 유형도 포함됩니다.

  • 토큰
  • 참조
  • 수량

각 데이터 유형에는 값을 지정하는 고유한 구문이 있습니다. 각 데이터 유형은 검색 수행 방법을 변경하는 한정자를 지원합니다.

다음 섹션에서는 데이터 유형을 사용하는 방법을 보여줍니다. 추가 데이터 유형, 값 구문, 한정자에 대한 자세한 내용은 고급 FHIR 검색 기능을 참조하세요.

숫자

정수 또는 부동 소수점 값으로 검색합니다. 비교 연산자를 변경하려면 값 앞에 다음 한정자 중 하나를 추가합니다.

  • ne
  • lt
  • le
  • gt
  • ge

예를 들어 동등에는 [parameter]=100을 사용하고 100 이상인 경우에는 [parameter]=ge100을 사용합니다.

날짜

모든 날짜, 시간, 기간 유형으로 검색합니다. 날짜 매개변수 형식은 다음과 같습니다.

yyyy-mm-ddThh:mm:ss[Z|(+|-)hh:mm]

number에 사용된 것과 동일한 프리픽스 한정자가 적용됩니다.

문자열

대소문자, 악센트, 기타 구별 부호를 구분하지 않는 프리픽스 검색 기본값

토큰

'code'와 정확히 일치하는 문자열을 검색합니다. 다음 형식을 사용하여 코드를 가져온 값의 집합을 나타내는 '시스템'의 URI로 검색 범위를 지정할 수 있습니다.

[parameter]=[system]|[code]

예를 들어 다음 검색은 지정된 URI가 있는 코딩 시스템의 값으로 정규화된 경우에만 10738-3 코드와 일치합니다.

code=http://hl7.org/fhir/ValueSet/observation-codes|10738-3

수량

number와 동일한 프리픽스 한정자를 사용하여 숫자 값을 검색합니다. 다음과 같은 형식의 값 단위를 나타내는 특정 시스템과 코드로 검색을 한정할 수 있습니다.

[parameter]=[prefix][number]|[system]|[code]

예를 들어 다음 쿼리는 지정된 단위 체계 및 코드가 있는 9.1 미만의 수량 값을 검색합니다.

value-quantity=lt9.1|http://unitsofmeasure.org|mg

참조

리소스 간 참조를 검색합니다. FHIR 저장소 내부의 리소스에 대한 참조에 다음 쿼리를 사용할 수 있습니다.

  • [parameter]=[id]
  • [parameter]=[type]/[id]

[parameter]=[url]을 사용하여 FHIR 저장소 외부에 있을 수 있는 URL별로 참조를 지정할 수 있습니다.

검색 매개변수 처리

기본적으로 검색 메서드는 검색이 인식하지 못하는 매개변수를 무시하는 '관대한' 처리를 적용합니다. 검색 메서드는 요청에 남아 있는 매개변수를 사용하여 검색을 수행하므로 예상보다 많은 리소스가 반환될 수 있습니다.

응답에는 다음이 포함됩니다.

  • Bundle.link.relation = self의 값을 가진 Bundle.link의 값
  • 검색에 성공적으로 적용된 매개변수만 포함된 URL의 Bundle.link.url입니다. 이 값을 검사하여 매개변수가 무시되었는지 확인할 수 있습니다.

검색 요청 시 요청 HTTP 헤더를 Prefer: handling=strict로 설정할 수 있습니다. 헤더를 설정하면 FHIR 저장소가 인식할 수 없는 매개변수에 오류를 반환합니다.