기존 번들 서비스용 Search API

Search API는 구조화된 데이터가 포함된 문서를 색인화하는 모델을 제공합니다. 색인을 검색하고 검색결과를 정렬하여 나타낼 수 있습니다. 이 API는 문자열 필드에 대한 전체 텍스트 일치를 지원합니다. 문서와 색인은 검색 작업에 최적화된 별도의 영구 스토리지에 저장됩니다. Search API로 색인화할 수 있는 문서 수에는 제한이 없습니다. 매우 큰 결과 집합을 검색해야 하는 애플리케이션에는 App Engine Datastore가 더 적합할 수 있습니다.

개요

Search API는 문서, 색인, 쿼리, 결과라는 네 가지 기본 개념을 기반으로 합니다.

문서

문서란 사용자 데이터가 포함된 필드 목록과 고유한 ID가 있는 객체를 말합니다. 각 필드에는 이름과 유형이 있습니다. 필드에는 포함된 값의 종류에 따라 구분되는 다음과 같은 여러 유형이 있습니다.

  • Atom 필드 - 분할할 수 없는 문자열
  • 텍스트 필드 - 단어 단위로 검색할 수 있는 일반 텍스트 문자열
  • HTML 필드 - HTML 마크업 태그를 포함하는 문자열. 마크업 태그 외부의 텍스트만 검색 가능
  • 숫자 필드 - 부동 소수점 숫자
  • 날짜 필드 - 날짜 객체
  • 지리 좌표 필드 - 위도와 경도 좌표가 있는 데이터 객체

문서 하나의 최대 크기는 1MB입니다.

색인

색인은 검색을 위해 문서를 저장합니다. 단일 문서는 ID로, 문서 범위는 연속된 ID로 검색할 수 있으며 색인의 모든 문서를 검색할 수도 있습니다. 또한 색인을 검색하여 쿼리 문자열로 지정된 필드와 필드 값에 대한 특정 기준을 충족하는 문서를 가져올 수 있습니다. 또한 여러 문서를 서로 다른 색인에 추가하여 그룹으로 관리할 수 있습니다.

색인에 추가할 수 있는 문서 수 또는 사용할 수 있는 색인 수에는 제한이 없습니다. 색인 하나에 포함된 모든 문서의 전체 크기는 기본적으로 10GB로 제한됩니다. App Engine 관리자 역할이 있는 사용자는 Google Cloud 콘솔 App Engine Search 페이지에서 요청을 제출하여 크기를 최대 200GB까지 늘릴 수 있습니다.

쿼리

색인을 검색하려면 쿼리 문자열과 몇 가지 추가 옵션으로 이루어진 쿼리를 구성해야 합니다. 쿼리 문자열은 하나 이상의 문서 필드 값에 대한 조건을 지정합니다. 색인을 검색하면 색인의 문서 중 해당 필드가 쿼리를 충족하는 문서만 반환됩니다.

가장 간단한 쿼리는 필드 값만 들어있는 문자열입니다. 이러한 쿼리를 '전체 검색'이라고도 합니다. 다음 검색에서는 'rose'와 'water'라는 단어가 포함된 문서를 검색하는 문자열을 사용합니다.

index.search("rose water");

다음은 날짜 필드에 날짜 1776년 7월 4일 또는 텍스트 필드에 문자열 '1776-07-04'가 포함된 문서를 검색합니다.

index.search("1776-07-04");

쿼리 문자열을 더욱 구체적으로 구성할 수 있습니다. 필드 및 필드 값에 대한 제약조건을 지정하는 하나 이상의 항을 포함할 수 있습니다. 항의 정확한 형식은 필드 유형에 따라 다릅니다. 예를 들어 'product'라는 텍스트 필드와 'price'라는 숫자 필드가 있는 경우 두 항을 포함하는 쿼리 문자열은 다음과 같습니다.

// search for documents with pianos that cost less than $5000
index.search("product = piano AND price < 5000");

쿼리 옵션은 이름에서 알 수 있듯이 필수 항목은 아니며, 다음과 같이 다양한 기능을 제공합니다.

  • 검색결과에 반환되는 문서 수를 제어합니다.
  • 결과에 포함할 문서 필드를 지정합니다. 기본 동작은 원본 문서의 모든 필드를 포함하는 것입니다. 필드 중 일부만 결과에 포함되도록 지정할 수 있으며, 원본 문서에는 영향이 없습니다.
  • 결과를 정렬합니다.
  • FieldExpressions를 사용하여 문서에 '계산 필드'를 만들고 스니펫을 사용하여 요약 텍스트 필드를 만듭니다.
  • 오프셋과 커서를 사용하여 각 쿼리에서 일치하는 문서 중 일부만 반환함으로써 검색결과에 대한 페이징을 지원합니다.

실행된 쿼리 레코드를 보관하려면 애플리케이션에서 쿼리 문자열을 로깅하는 것이 좋습니다.

검색결과

search() 호출은 일치하는 문서 중 일부만 반환할 수 있습니다. 따라서 검색을 통해 단일 호출로 반환되는 것보다 더 많은 문서를 찾을 수 있습니다. 각 검색 호출은 Results 클래스의 인스턴스를 반환합니다. 해당 인스턴스에는 반환된 문서의 목록과 함께 검색한 문서 수와 반환된 문서 수에 대한 정보가 있습니다. 커서 또는 오프셋을 사용하여 동일한 검색을 반복하면 일치하는 전체 문서 집합을 검색할 수 있습니다.

추가 교육 자료

이 문서 외에도 Google 개발자 아카데미에서 Search API에 관한 2부작 교육 강의를 참조할 수 있습니다. (이 강의에서는 Python API를 사용하지만, 검색이라는 개념에 대한 추가 내용이 도움이 될 수 있습니다.)

문서 및 필드

Document 클래스는 문서를 나타냅니다. 각 문서에는 문서 식별자필드 목록이 있습니다.

문서 식별자

색인에 포함된 모든 문서에는 고유한 문서 식별자, 즉 doc_id가 있어야 합니다. 식별자를 사용하면 검색을 수행하지 않고 색인에서 문서를 가져올 수 있습니다. 기본적으로 Search API는 문서를 만들 때 자동으로 doc_id를 생성합니다. 또한 문서를 만들 때 doc_id를 직접 지정할 수 있습니다. doc_id는 육안 확인 및 인쇄가 가능한 ASCII 문자(ASCII 코드 33~126, 경계 포함)로만 구성되어야 하며 500자를 초과할 수 없습니다. 또한 맨 앞에 느낌표('!')가 올 수 없으며 맨 앞이나 맨 뒤에 연속된 2개의 밑줄('__')이 올 수 없습니다.

읽기 쉽고 의미 있는 고유한 문서 식별자를 만드는 것이 편리하긴 하지만 doc_id를 검색에 포함할 수는 없습니다. 예를 들어 색인에 포함된 문서가 부품을 나타내며 부품의 일련번호를 doc_id로 사용한다고 가정해 보겠습니다. 이 경우 단일 부품에 대한 문서는 매우 효율적으로 검색할 수 있지만, 구매 날짜 등의 다른 필드 값과 함께 특정 범위의 일련번호를 검색할 수 없게 됩니다. 일련번호를 Atom 필드에 저장하면 이러한 문제가 없습니다.

문서 필드

문서는 이름, 유형, 해당 유형의 단일 을 갖는 필드를 포함합니다. 유형이 서로 다른 두 개 이상의 필드가 동일한 이름을 가질 수도 있습니다. 예를 들어 'age'라는 이름으로 두 필드를 정의하면서 한 필드에는 텍스트 유형(값: 'twenty-two')을, 다른 한 필드에는 숫자 유형(값: 22)을 사용할 수 있습니다.

필드 이름

필드 이름은 대소문자를 구분하며 ASCII 문자만 포함할 수 있습니다. 문자로 시작해야 하며 문자, 숫자, 밑줄로 구성될 수 있습니다. 필드 이름은 500자를 초과할 수 없습니다.

다중 값 필드

필드는 필드 유형과 일치하는 하나의 값만 포함할 수 있습니다. 고유한 필드 이름을 사용할 필요는 없습니다. 문서는 이름과 유형이 같은 여러 필드를 가질 수 있으며, 이 방법으로 다중 값 필드를 나타낼 수 있습니다. 그러나 동일한 이름을 가진 날짜 필드와 숫자 필드를 반복할 수는 없습니다. 문서에 이름이 같지만 유형은 다른 여러 필드가 포함될 수도 있습니다.

필드 유형

java.lang.String 문자열을 저장하는 필드에는 세 가지 종류가 있으며, 이러한 필드를 문자열 필드라고 통칭합니다.

  • 텍스트 필드: 최대 길이가 1024**2자인 문자열입니다.
  • HTML 필드: 최대 길이가 1024**2자인 HTML 형식의 문자열입니다.
  • Atom 필드: 최대 길이가 500자인 문자열입니다.

또한 텍스트가 아닌 데이터를 저장하는 세 가지 필드 유형이 있습니다.

  • 숫자 필드: -2,147,483,647에서 2,147,483,647 사이의 배정밀도 부동 소수점 값입니다.
  • 날짜 필드: java.util.Date입니다.
  • 지리 좌표 필드: 위도와 경도 좌표로 표현되는 지구상의 한 지점

필드 유형은 Field.FieldType열거형 TEXT, HTML, ATOM, NUMBER, DATE, GEO_POINT를 사용하여 지정됩니다.

문자열 및 날짜 필드의 특수 처리

날짜, 텍스트, HTML 필드가 있는 문서가 색인에 추가되면 몇 가지 특수 처리가 실행됩니다. 시스템이 내부적으로 어떻게 작동하는지 이해하면 Search API를 효과적으로 사용하는 데 도움이 됩니다.

문자열 필드 토큰화

HTML 또는 텍스트 필드를 색인화하면 필드의 내용이 토큰화됩니다. 즉, 문자열이 공백 또는 특수문자(문장부호, 해시 기호, 백슬래시 등)가 나타나는 모든 위치를 기준으로 여러 토큰으로 분할됩니다. 색인에는 각 토큰에 대한 항목이 포함됩니다. 이렇게 하면 필드 값의 일부만으로 구성된 키워드와 구문을 검색할 수 있습니다. 예를 들어 'dark'를 검색하면 'it was a dark and stormy night' 문자열이 포함된 텍스트 필드가 있는 문서가 검색되고, 'time'을 검색하면 'this is a real-time system' 문자열이 포함된 텍스트 필드가 있는 문서가 검색됩니다.

HTML 필드에서 마크업 태그로 묶인 텍스트는 토큰화되지 않으므로 it was a <strong>dark</strong> night를 포함하는 HTML 필드가 있는 문서는 'night'로는 검색되지만 'strong'으로는 검색되지 않습니다. 마크업 텍스트를 검색하려면 텍스트 필드에 저장해야 합니다.

Atom 필드는 토큰화되지 않습니다. 값이 'bad weather'인 Atom 필드가 있는 문서는 전체 문자열 'bad weather'로만 검색됩니다. 'bad' 또는 'weather' 단독으로는 검색되지 않습니다.

토큰화 규칙
  • 밑줄(_)과 앰퍼샌드(&) 문자는 단어를 토큰으로 나누지 않습니다.

  • 공백, 캐리지 리턴, 라인 피드, 가로 탭, 세로 탭, 폼 피드, NULL과 같은 공백 문자는 항상 단어를 토큰으로 나눕니다.

  • 다음 문자는 문장부호로 취급되며 단어를 토큰으로 나눕니다.

    !"%()
    *,-|/
    []]^`
    :=>?@
    {}~$
  • 다음 표에 나온 문자는 일반적으로 단어를 토큰으로 나누지만 어떠한 상황에서 나타났는지에 따라 다르게 처리될 수 있습니다.

    문자 규칙
    < HTML 필드에서 '미만' 기호는 HTML 태그의 시작을 나타내며 무시됩니다.
    + 하나 이상의 '더하기' 기호로 이루어진 문자열은 C++와 같이 단어 끝에 사용될 경우 단어의 일부로 취급됩니다.
    # '해시' 기호는 a, b, c, d, e, f, g, j, x가 앞에 올 경우 단어의 일부로 취급됩니다. a# ~ g#은 음표, j#과 x#은 프로그래밍 언어, c#은 둘 다에 해당합니다. #google과 같이 단어 에 '#'이 올 경우 해시태그로 취급되어 해시가 단어의 일부가 됩니다.
    ' 아포스트로피는 'John's hat'과 같이 문자 's'와 단어 분리 문자가 연달아 뒤에 올 경우 문자로 취급됩니다.
    . 숫자 사이의 소수점은 소수 구분기호로서 숫자의 일부로 취급됩니다. A.B.C와 같이 약어에 사용된 경우에도 단어의 일부로 취급될 수 있습니다.
    - I-B-M과 같이 약어에 사용된 대시는 단어의 일부입니다.
  • 문자와 숫자('A-Z', 'a-z', '0-9')를 제외한 다른 7비트 문자는 모두 문장부호로 취급되며 단어를 토큰으로 나눕니다.

  • 그 외 나머지 경우는 UTF-8 문자로 파싱됩니다.

약어

토큰화에서는 특수한 규칙을 사용하여 'I.B.M', 'a-b-c', 'C I A' 등의 약어를 인식합니다. 약어는 여러 영문자를 한 글자씩 동일한 구분문자로 나눈 문자열입니다. 사용 가능한 구분기호는 마침표, 대시, 임의 개수의 공백입니다. 구분문자는 약어가 토큰화될 때 문자열에서 삭제됩니다. 따라서 위에서 예시로 든 문자열은 'ibm', 'abc', 'cia'로 토큰화됩니다. 원본 텍스트는 문서 필드에 유지됩니다.

약어를 다룰 때 주의할 점은 다음과 같습니다.

  • 약어는 21자를 초과할 수 없습니다. 유효하지만 21자를 초과하는 약어 문자열은 각각 21자 이하의 연속된 여러 약어로 분할됩니다.
  • 약어의 문자가 공백으로 구분된 경우 대소문자를 혼용할 수 없습니다. 마침표와 대시로 구분된 약어는 대소문자를 혼용할 수 있습니다.
  • 약어를 검색할 때는 약어의 표준 형식(구분기호 없는 문자열)을 입력할 수도 있고, 각 문자를 대시 또는 점으로 구분한 약어를 입력할 수도 있지만 대시와 점을 혼용할 수는 없습니다. 따라서 텍스트 'I.B.M'을 검색하려는 경우 'I-B-M', 'I.B.M', 'IBM' 모두 검색어로 사용할 수 있습니다.

날짜 필드 정확도

문서에 날짜 필드를 만들 때 값을 java.util.Date로 설정합니다. 날짜 필드를 색인화하고 검색할 수 있도록 시간 구성요소는 모두 무시되며 날짜는 1970년 1월 1일(UTC) 이후 경과된 날짜 수로 변환됩니다. 즉, 날짜 필드에는 정확한 시간 값이 포함될 수 있지만 날짜 쿼리에는 yyyy-mm-dd 형식으로만 날짜 필드 값을 지정할 수 있습니다. 따라서 여러 날짜 필드가 같은 날짜를 포함할 경우 정렬 순서가 명확히 정의되지 않습니다.

기타 문서 속성

문서의 순위는 검색 시 반환되는 문서의 기본 순서를 결정하는 양의 정수입니다. 기본적으로 순위는 문서 생성 시점에 설정되며 값은 2011년 1월 1일 이후 경과된 초 수입니다. 문서를 만들 때 명시적으로 순위를 설정할 수 있습니다. 여러 문서에 같은 순위를 할당하지 않는 것이 좋습니다. 또한 문서 10,000개 이상에 같은 순위를 부여해서는 안 됩니다. 정렬 옵션을 지정하는 경우 순위를 정렬 키로 사용할 수 있습니다. 순위가 정렬 표현식 또는 필드 표현식에 사용되면 _rank로 참조됩니다.

언어 속성은 필드가 인코딩되는 언어를 지정합니다.

이러한 속성에 대한 자세한 내용은 Document 클래스 참조 페이지를 참조하세요.

문서에서 다른 리소스로 연결

문서의 doc_id와 기타 필드를 애플리케이션의 다른 리소스로 연결되는 링크로 사용할 수 있습니다. 예를 들어 Blobstore를 사용하는 경우 doc_id 또는 Atom 필드 값을 데이터의 BlobKey로 설정하여 문서에 특정 blob을 연결할 수 있습니다.

문서 만들기

문서를 만들려면 Document.newBuilder() 메서드를 사용하여 새 빌더를 요청합니다. 애플리케이션이 빌더에 액세스하면 선택적 문서 식별자를 지정하고 필드를 추가할 수 있습니다.

문서와 마찬가지로 빌더를 사용하여 필드를 만들 수 있습니다. Field.newBuilder() 메서드는 필드 이름과 값을 지정할 수 있는 필드 빌더를 반환합니다. 필드 유형은 특별히 설정된 메서드를 선택하면 자동으로 지정됩니다. 예를 들어 필드가 일반 텍스트를 포함하고 있음을 나타내려면 setText()를 호출합니다. 다음 코드는 방명록 인사말을 나타내는 필드가 있는 문서를 빌드합니다.

User currentUser = UserServiceFactory.getUserService().getCurrentUser();
String userEmail = currentUser == null ? "" : currentUser.getEmail();
String userDomain = currentUser == null ? "" : currentUser.getAuthDomain();
String myDocId = "PA6-5000";
Document doc =
    Document.newBuilder()
        // Setting the document identifer is optional.
        // If omitted, the search service will create an identifier.
        .setId(myDocId)
        .addField(Field.newBuilder().setName("content").setText("the rain in spain"))
        .addField(Field.newBuilder().setName("email").setText(userEmail))
        .addField(Field.newBuilder().setName("domain").setAtom(userDomain))
        .addField(Field.newBuilder().setName("published").setDate(new Date()))
        .build();

문서 내의 필드에 액세스하려면 다음과 같이 getOnlyField()를 사용합니다.

String coverLetter = document.getOnlyField("coverLetter").getText();
String resume = document.getOnlyField("resume").getHTML();
String fullName = document.getOnlyField("fullName").getAtom();
Date submissionDate = document.getOnlyField("submissionDate").getDate();

색인 작업

색인에 문서 추가

색인에 문서를 추가하면 문서가 영구 스토리지에 복사되고 각 필드가 이름, 유형, doc_id에 따라 색인화됩니다.

다음 코드 예시에서는 색인에 액세스하고 문서를 색인에 추가하는 방법을 보여줍니다. 단계는 다음과 같습니다.

public static void indexADocument(String indexName, Document document)
    throws InterruptedException {
  IndexSpec indexSpec = IndexSpec.newBuilder().setName(indexName).build();
  Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);

  final int maxRetry = 3;
  int attempts = 0;
  int delay = 2;
  while (true) {
    try {
      index.put(document);
    } catch (PutException e) {
      if (StatusCode.TRANSIENT_ERROR.equals(e.getOperationResult().getCode())
          && ++attempts < maxRetry) { // retrying
        Thread.sleep(delay * 1000);
        delay *= 2; // easy exponential backoff
        continue;
      } else {
        throw e; // otherwise throw
      }
    }
    break;
  }
}
한 번에 최대 200개의 문서를 put() 메서드에 전달할 수 있습니다. 문서를 한 번에 하나씩 추가하기보다 일괄 추가하는 방법이 효율적입니다.

색인에 문서를 추가할 때 doc_id가 동일한 문서가 색인에 이미 있는 경우 새 문서가 기존 문서를 대체합니다. 별도의 경고는 없습니다. 문서를 만들거나 색인에 추가하기 전에 Index.get(id)을 호출하면 특정 doc_id가 이미 있는지 확인할 수 있습니다.

Index 클래스의 인스턴스가 생성되었더라도 영구 색인이 실제로 존재한다는 보장은 없습니다. 영구 색인은 put 메서드를 사용하여 문서를 처음 추가하면 만들어집니다. 색인을 사용하기 전에 색인이 실제로 존재하는지 확인하려면 SearchService.getIndexes() 메서드를 사용합니다.

문서 업데이트

문서를 색인에 추가하고 나면 문서를 변경할 수 없으며 필드 추가, 삭제, 필드 값 변경도 불가능합니다. 그러나 새 문서의 doc_id가 같으면 기존 문서를 대체할 수는 있습니다.

doc_id로 문서 검색

문서 식별자를 사용하여 색인에서 문서를 검색하는 방법에는 두 가지가 있습니다.
  • Index.get()을 사용하여 doc_id로 단일 문서를 가져옵니다.
  • Index.getRange()를 사용하여 doc_id로 정렬된 연속된 문서 그룹을 검색합니다.

아래 예시에서는 각 호출을 보여줍니다.

IndexSpec indexSpec = IndexSpec.newBuilder().setName(INDEX).build();
Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);

// Fetch a single document by its  doc_id
Document doc = index.get("AZ125");

// Fetch a range of documents by their doc_ids
GetResponse<Document> docs =
    index.getRange(GetRequest.newBuilder().setStartId("AZ125").setLimit(100).build());

콘텐츠로 문서 검색

색인에서 문서를 검색하려면 쿼리 문자열을 구성하고 Index.search()를 호출합니다. 쿼리 문자열을 인수로 직접 전달하거나 인수로 전달되는 쿼리 객체에 문자열을 포함할 수 있습니다. 기본적으로 search()는 일치하는 문서를 내림차순으로 정렬하여 반환합니다. 반환되는 문서 수 또는 정렬 방법을 제어하거나 결과에 계산 필드를 추가하려면 Query 객체를 사용해야 합니다. 이 객체는 쿼리 문자열을 포함하며 다른 검색 및 정렬 옵션을 지정할 수도 있습니다.

final int maxRetry = 3;
int attempts = 0;
int delay = 2;
while (true) {
  try {
    String queryString = "product = piano AND price < 5000";
    Results<ScoredDocument> results = getIndex().search(queryString);

    // Iterate over the documents in the results
    for (ScoredDocument document : results) {
      // handle results
      out.print("maker: " + document.getOnlyField("maker").getText());
      out.println(", price: " + document.getOnlyField("price").getNumber());
    }
  } catch (SearchException e) {
    if (StatusCode.TRANSIENT_ERROR.equals(e.getOperationResult().getCode())
        && ++attempts < maxRetry) {
      // retry
      try {
        Thread.sleep(delay * 1000);
      } catch (InterruptedException e1) {
        // ignore
      }
      delay *= 2; // easy exponential backoff
      continue;
    } else {
      throw e;
    }
  }
  break;
}

색인 삭제

각 색인은 색인이 생성된 문서와 색인 스키마로 구성됩니다. 색인을 삭제하려면 색인의 모든 문서를 삭제한 후 색인 스키마를 삭제합니다.

색인에서 문서를 삭제하려면 삭제하려는 문서의 doc_iddelete() 메서드로 지정합니다. 효율을 높이려면 문서를 일괄 삭제해야 합니다. 한 번에 문서 ID를 최대 200개까지 delete() 메서드에 전달할 수 있습니다.

try {
  // looping because getRange by default returns up to 100 documents at a time
  while (true) {
    List<String> docIds = new ArrayList<>();
    // Return a set of doc_ids.
    GetRequest request = GetRequest.newBuilder().setReturningIdsOnly(true).build();
    GetResponse<Document> response = getIndex().getRange(request);
    if (response.getResults().isEmpty()) {
      break;
    }
    for (Document doc : response) {
      docIds.add(doc.getId());
    }
    getIndex().delete(docIds);
  }
} catch (RuntimeException e) {
  LOG.log(Level.SEVERE, "Failed to delete documents", e);
}
한 번에 최대 200개의 문서를 delete() 메서드에 전달할 수 있습니다. 한 번에 하나씩 삭제하기보다 일괄 삭제하는 방법이 효율적입니다.

Eventual consistency

색인에 문서를 추가, 업데이트 또는 삭제하면 변경사항이 여러 데이터 센터로 전파됩니다. 일반적으로 전파 속도는 매우 빠르지만 소요 시간은 일정하지 않습니다. Search API는 eventual consistency를 보장합니다. 경우에 따라 하나 이상의 문서를 검색하면 최신 변경사항이 반영되지 않은 결과가 반환될 수 있습니다.

색인 크기 결정

색인은 검색을 위해 문서를 저장합니다. 단일 문서는 ID로, 문서 범위는 연속된 ID로 검색할 수 있으며 색인의 모든 문서를 검색할 수도 있습니다. 또한 색인을 검색하여 쿼리 문자열로 지정된 필드와 필드 값에 대한 특정 기준을 충족하는 문서를 가져올 수 있습니다. 또한 여러 문서를 서로 다른 색인에 추가하여 그룹으로 관리할 수 있습니다. 색인에 추가할 수 있는 문서 수 또는 사용할 수 있는 색인 수에는 제한이 없습니다. 색인 하나에 포함된 모든 문서의 전체 크기는 기본적으로 10GB로 제한되지만, Google Cloud 콘솔의 App Engine Search 페이지에서 요청을 제출하면 최대 200GB까지 늘릴 수 있습니다. Index.getStorageLimit() 메서드는 색인의 최대 허용 크기를 반환합니다.

Index.getStorageUsage() 메서드는 색인이 사용하는 저장공간 용량의 추정치입니다. 색인 모니터링 시스템은 지속적으로 실행되지 않으므로 이 수치는 추정치이며 실제 사용량은 주기적으로 계산됩니다. storage_usage는 문서 추가를 고려하여 샘플링 시점 간에 조정되지만 삭제는 고려하지 않습니다.

색인 스키마

모든 색인에는 포함된 문서에 나타나는 모든 필드 이름과 필드 유형을 보여주는 스키마가 있습니다. 스키마는 직접 정의할 수 없습니다. 스키마는 문서가 색인에 추가될 때 업데이트되며 동적으로 유지 관리됩니다. 간단한 스키마는 다음과 같이 JSON과 유사한 형식입니다.

{'comment': ['TEXT'], 'date': ['DATE'], 'author': ['TEXT'], 'count': ['NUMBER']}

사전의 각 키는 문서 필드의 이름입니다. 키 값은 해당 필드 이름과 함께 사용된 필드 유형의 목록입니다. 이름은 같고 유형은 서로 다른 여러 필드를 사용한 경우 스키마는 다음과 같이 필드 이름 하나에 두 개 이상의 필드 유형을 나열합니다.

{'ambiguous-integer': ['TEXT', 'NUMBER', 'ATOM']}

스키마에 한 번 표시된 필드는 어떠한 경우에도 삭제할 수 없습니다. 색인에 더 이상 해당 필드 이름을 갖는 문서가 없더라도 필드를 삭제할 수는 없습니다.

색인의 스키마를 확인하는 방법은 다음과 같습니다.

GetResponse<Index> response =
    SearchServiceFactory.getSearchService()
        .getIndexes(GetIndexesRequest.newBuilder().setSchemaFetched(true).build());

// List out elements of each Schema
for (Index index : response) {
  Schema schema = index.getSchema();
  for (String fieldName : schema.getFieldNames()) {
    List<FieldType> typesForField = schema.getFieldTypes(fieldName);
    // Just printing out the field names and types
    for (FieldType type : typesForField) {
      out.println(index.getName() + ":" + fieldName + ":" + type.name());
    }
  }
}
GetIndexes() 호출이 반환하는 색인은 1,000개를 초과할 수 없습니다. 더 많은 색인을 검색하려면 GetIndexesRequest.Builder와 함께 setStartIndexName()을 사용하여 메서드를 반복적으로 호출합니다.

스키마는 객체 프로그래밍으로의 '클래스'를 정의하지 않습니다. Search API의 체계에서는 모든 문서가 고유하며 색인은 다양한 유형의 문서를 포함할 수 있습니다. 동일한 필드 목록을 가진 여러 객체의 컬렉션을 클래스의 인스턴스로 간주하려는 경우 코드에서 직접 추상화를 적용해야 합니다. 예를 들어 동일한 필드 집합을 가진 모든 문서를 자체 색인에 보관할 수 있습니다. 색인 스키마는 클래스 정의로, 색인의 각 문서는 클래스의 인스턴스로 볼 수 있습니다.

Google Cloud 콘솔에서 색인 보기

Google Cloud 콘솔에서 애플리케이션의 색인 및 색인에 포함된 문서에 대한 정보를 열람할 수 있습니다. 색인 이름을 클릭하면 색인에 포함된 문서가 표시됩니다. 색인에 정의된 스키마 필드가 모두 표시되고, 해당 이름의 필드를 갖는 각 문서의 필드 값이 표시됩니다. 콘솔에서 색인 데이터에 대한 쿼리를 직접 실행할 수도 있습니다.

Search API 할당량

Search API에는 몇 가지 무료 할당량이 제공됩니다.

리소스 또는 API 호출 무료 할당량
총 저장용량(문서 및 색인) 0.25GB
쿼리 쿼리 1,000개/일
색인에 문서 추가 0.01GB/일

Search API는 이러한 한도를 적용하여 서비스의 안정성을 보장합니다. 무료 앱과 유료 앱 모두에 한도가 적용됩니다.

리소스 안전 할당량
최대 쿼리 사용량 분당 쿼리 실행 누적 시간 100분
추가 또는 삭제되는 최대 문서 15,000/분
색인당 최대 크기(색인 수는 제한 없음) 10GB

API 사용량은 호출 유형에 따라 다양한 방식으로 계산됩니다.

  • Index.search(): 각 API 호출은 쿼리 1회로 계산됩니다. 실행 시간은 호출 지연 시간과 동일합니다.
  • Index.put(): 색인에 문서를 추가할 때 각 문서의 크기와 문서 수가 색인이 생성된 할당량에 합산됩니다.
  • 다른 모든 Search API 호출은 관련 작업 수를 기준으로 계산됩니다.
    • SearchService.getIndexes(): 각 색인이 실제로 반환될 때마다 또는 아무것도 반환되지 않은 경우 작업 1회로 계산됩니다.
    • Index.get()Index.getRange(): 각 문서가 실제로 반환될 때마다 또는 아무것도 반환되지 않은 경우 작업 1회로 계산됩니다.
    • Index.delete(): 요청에 포함된 문서 1개당 또는 요청이 비어 있는 경우 작업 1회로 계산됩니다.

쿼리 처리량에 할당량이 적용되는 이유는 사용자 한 명이 검색 서비스를 독점하지 못하도록 하기 위함입니다. 여러 쿼리가 동시에 실행될 수 있으므로 각 애플리케이션은 클럭 시간 1분당 실행 시간을 최대 100분까지 소비하는 쿼리를 실행할 수 있습니다. 짧은 쿼리를 여러 개 실행하면 이 한도에 도달할 가능성이 거의 없습니다. 할당량을 초과하면 할당량이 복원되는 다음 타임 슬라이스까지 후속 쿼리가 실패합니다. 할당량은 1분 단위로 엄격하게 적용되지 않으며, 변형된 leaky bucket 알고리즘을 사용하여 5초 단위로 검색 대역폭을 제어합니다.

할당량에 대한 자세한 내용은 할당량 페이지를 참조하세요. 앱에서 이러한 할당량을 초과하려고 하면 할당량 부족 오류가 반환됩니다.

이러한 한도는 분당으로 적용되지만 콘솔에서는 각 항목의 일일 총계가 표시됩니다. 실버, 골드, 플래티넘 지원을 신청한 고객은 지원팀 담당자에게 처리량 한도 상향을 요청할 수 있습니다.

Search API 가격 책정

무료 할당량을 넘어선 사용량에는 다음과 같이 청구가 적용됩니다.

리소스 비용
총 저장용량(문서 및 색인) GB당 $0.18/월
쿼리 쿼리 10,000개당 $0.50
검색 가능한 문서의 색인 생성 GB당 $2.00

가격 책정에 대한 추가 정보는 가격 책정 페이지를 참조하세요.