콘텐츠 커넥터 만들기

콘텐츠 커넥터는 엔터프라이즈 저장소의 데이터를 순회하고 데이터 소스를 채우는 데 사용되는 소프트웨어 프로그램입니다. Google은 콘텐츠 커넥터 개발을 위해 다음과 같은 옵션을 제공합니다.

  • 콘텐츠 커넥터 SDK 자바로 프로그래밍하는 경우에 적합한 옵션입니다. REST API를 둘러싸는 래퍼로서 커넥터를 빠르게 생성할 수 있게 해줍니다. SDK를 사용하여 콘텐츠 커넥터를 만들려면 콘텐츠 커넥터 SDK를 사용하여 콘텐츠 커넥터 만들기를 참조하세요.

  • 하위 수준 REST API 또는 API 라이브러리: 자바에서 프로그래밍하지 않는 경우 또는 코드베이스가 REST API나 라이브러리에 더 적합한 경우 이 옵션을 사용하세요. REST API를 사용하여 콘텐츠 커넥터를 만들려면 REST API를 사용하여 콘텐츠 커넥터 만들기를 참조하세요.

콘텐츠 커넥터는 일반적으로 다음의 작업을 수행합니다.

  1. 구성 매개변수를 읽고 처리합니다.
  2. 타사 콘텐츠 저장소에서 '항목'이라는 색인 생성이 가능한 데이터의 개별 청크를 가져옵니다.
  3. ACL, 메타데이터, 콘텐츠 데이터를 색인 생성이 가능한 항목으로 결합합니다.
  4. 항목의 색인을 Cloud Search 데이터 소스로 생성합니다.
  5. (선택사항) 타사 콘텐츠 저장소로부터의 변경 알림 신호를 수신합니다. 변경 알림은 색인 생성 요청으로 변환되어 Cloud Search 데이터 소스를 타사 저장소와 동기화된 상태로 유지합니다. 커넥터는 저장소가 변경 감지를 지원하는 경우에만 이 태스크를 수행합니다.

콘텐츠 커넥터 SDK를 사용하여 콘텐츠 커넥터 만들기

다음 섹션에서는 콘텐츠 커넥터 SDK를 사용하여 콘텐츠 커넥터를 만드는 방법을 설명합니다.

종속 항목 설정

SDK를 사용하려면 빌드 파일에 특정 종속 항목을 포함해야 합니다. 아래 탭을 클릭하여 빌드 환경의 종속 항목을 확인하세요.

Maven

<dependency>
<groupId>com.google.enterprise.cloudsearch</groupId>
<artifactId>google-cloudsearch-indexing-connector-sdk</artifactId>
<version>v1-0.0.3</version>
</dependency>

Gradle

compile group: 'com.google.enterprise.cloudsearch',
        name: 'google-cloudsearch-indexing-connector-sdk',
        version: 'v1-0.0.3'

커넥터 구성 만들기

각 커넥터에는 커넥터에서 사용되는 매개변수(예: 저장소 ID)가 포함된 구성 파일이 있습니다. 매개변수는 키-값 쌍(예: api.sourceId=1234567890abcdef)으로 정의됩니다.

Google Cloud Search SDK에는 모든 커넥터에서 사용되는 Google 제공 구성 매개변수가 여러 개 포함되어 있습니다. 구성 파일에서 다음과 같은 Google 제공 매개변수를 선언해야 합니다.

  • 콘텐츠 커넥터의 경우 api.sourceIdapi.serviceAccountPrivateKeyFile을 선언해야 합니다. 이러한 매개변수가 저장소와 저장소에 액세스하는 데 필요한 비공개 키의 위치를 식별하기 때문입니다.
  • ID 커넥터의 경우 api.identitySourceId을 선언해야 합니다. 이 매개변수가 외부 ID 소스의 위치를 식별하기 때문입니다. 사용자를 동기화하는 경우 api.customerId도 기업의 Google Workspace 계정 고유 ID로 선언해야 합니다.

Google에서 제공하는 다른 매개변수의 기본 값을 재정의하려는 경우가 아니라면 구성 파일에서 매개변수를 선언하지 않아도 됩니다. Google에서 제공하는 구성 매개변수에 대한 자세한 내용(예: 특정 ID와 키를 생성하는 방법)은 Google에서 제공하는 구성 매개변수를 참조하세요.

구성 파일에 사용할 고유한 저장소별 매개변수도 정의할 수 있습니다.

커넥터에 구성 파일 전달

시스템 속성 config를 설정하여 커넥터에 구성 파일을 전달합니다. 커넥터를 시작할 때 -D 인수를 사용하여 속성을 설정할 수 있습니다. 예를 들어 다음 명령어는 MyConfig.properties 구성 파일을 사용하여 커넥터를 시작합니다.

java -classpath myconnector.jar;... -Dconfig=MyConfig.properties MyConnector

이 인수가 없으면 SDK는 connector-config.properties이라는 기본 구성 파일에 액세스하려고 시도합니다.

순회 전략 결정

콘텐츠 커넥터의 기본 기능은 저장소를 순회하고 데이터의 색인을 생성하는 것입니다. 저장소의 데이터 크기와 레이아웃을 기준으로 순회 전략을 구현해야 합니다. 직접 전략을 설계하거나 SDK에 구현된 다음 전략 중에서 선택할 수 있습니다.

전체 순회 전략

전체 순회 전략은 전체 저장소를 검사하여 무조건 모든 항목의 색인을 생성합니다. 이 전략은 일반적으로 저장소가 작고, 색인을 생성할 때마다 전체 순회를 수행하는 오버헤드를 감당할 수 있는 경우에 사용됩니다.

이 순회 전략은 주로 정적, 비계층적 데이터가 있는 소규모 저장소에 적합합니다. 변경 감지가 어렵거나 저장소에서 지원되지 않는 경우에도 이 순회 전략을 사용할 수 있습니다.

목록 순회 전략

목록 순회 전략은 모든 하위 노드를 포함한 전체 저장소를 검사하여 각 항목의 상태를 확인합니다. 그런 다음 커넥터가 두 번째 순회를 수행하여 새로운 항목 또는 마지막 색인 생성 후에 업데이트된 항목만 색인을 생성합니다. 이 전략은 색인을 업데이트할 때마다 전체 순회를 수행하는 대신 기존 색인에 증분 업데이트를 수행하기 위해 일반적으로 사용됩니다.

이 순회 전략은 변경 감지가 어렵거나 저장소에서 지원되지 않는 경우, 비계층적 데이터가 있는 경우, 아주 큰 데이터 세트를 사용하는 경우에 적합합니다.

그래프 순회

그래프 순회 전략은 전체 상위 노드를 검사하여 각 항목의 상태를 확인합니다. 그런 다음 커넥터가 두 번째 순회를 수행하여 새로운 루트 노드의 항목 또는 마지막 색인 생성 후에 업데이트된 항목에 대해서만 색인을 생성합니다. 마지막으로 커넥터는 모든 하위 ID를 전달한 다음 새로운 또는 업데이트된 하위 노드의 항목에 대하여 색인을 생성합니다. 커넥터는 모든 항목이 처리될 때까지 모든 하위 노드를 반복적으로 계속 순회합니다. 이러한 순회는 일반적으로 모든 ID를 나열하는 방법이 실용적이지 않은 계층 구조의 저장소에 사용됩니다.

이 전략은 일련의 디렉토리 또는 웹 페이지와 같이 계층적 데이터를 크롤링해야 하는 경우에 적합합니다.

이러한 각 순회 전략은 SDK의 템플릿 커넥터 클래스에 의해 구현됩니다. 순회 전략을 직접 구현할 수 있지만 이러한 템플릿을 사용하면 커넥터 개발 속도가 크게 향상됩니다. 템플릿을 사용하여 커넥터를 만들려면 순회 전략에 해당하는 섹션으로 진행하세요.

템플릿 클래스를 사용하여 전체 순회 커넥터 만들기

이 섹션에서는 FullTraversalSample 예시의 코드 스니펫을 참조합니다.

커넥터의 진입점 구현

커넥터의 진입점은 main() 메서드입니다. 이 메서드의 기본 작업은 Application 클래스의 인스턴스를 만들고 start() 메서드를 호출하여 커넥터를 실행하는 것입니다.

application.start()를 호출하기 전에 IndexingApplication.Builder 클래스를 사용하여 FullTraversalConnector 템플릿을 인스턴스화합니다. FullTraversalConnector는 메서드를 구현하는 Repository 객체를 허용합니다. 다음 코드 스니펫은 main() 메서드를 구현하는 방법을 보여줍니다.

FullTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a full
 * traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new FullTraversalConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

내부적으로 SDK는 커넥터의 main() 메서드가 Application.build를 호출한 후 initConfig() 메서드를 호출합니다. initConfig() 메서드는 다음 작업을 실행합니다.

  1. Configuation.isInitialized() 메서드를 호출하여 Configuration가 초기화되지 않았는지 확인합니다.
  2. Google에서 제공하는 키-값 쌍을 사용하여 Configuration 객체를 초기화합니다. 각 키-값 쌍은 Configuration 객체 내 ConfigValue 객체에 저장됩니다.

Repository 인터페이스 구현

Repository 객체의 유일한 목적은 저장소 항목의 순회와 색인 생성을 수행하는 것입니다. 템플릿을 사용하는 경우 콘텐츠 커넥터를 만들려면 Repository 인터페이스 내에서 특정 메서드를 재정의하기만 하면 됩니다. 재정의할 메소드는 사용하는 템플릿과 순회 전략에 따라 다릅니다. FullTraversalConnector의 경우 다음 메서드를 재정의합니다.

  • init() 메서드 데이터 저장소 설정 및 초기화를 실행하려면 init() 메서드를 재정의합니다.

  • getAllDocs() 메서드 데이터 저장소의 모든 항목을 순회하고 색인을 생성하려면 getAllDocs() 메서드를 재정의합니다. 이 메소드는(구성에 정의된 대로) 예약된 각 순회에 한 번씩 호출됩니다.

  • (선택사항) getChanges() 메서드. 저장소가 변경 감지를 지원하면 getChanges() 메서드를 재정의합니다. 이 메소드는 수정된 항목을 검색하고 그 색인을 생성하기 위해 (구성에 정의된 대로) 예약된 증분 순환마다 한 번씩 호출됩니다.

  • (선택사항) close() 메서드. 저장소 정리를 수행해야 하면 close() 메서드를 재정의합니다. 이 메서드는 커넥터 종료 시 한 번 호출됩니다.

Repository 객체의 각 메서드는 ApiOperation 객체의 일부 유형을 반환합니다. ApiOperation 객체는 저장소의 실제 색인 생성을 수행하기 위해 단일 호출 또는 다중 IndexingService.indexItem() 호출의 형태로 작업을 실행합니다.

커스텀 구성 매개변수 가져오기

커넥터 구성을 처리하려면 Configuration 객체에서 커스텀 매개변수를 가져와야 합니다. 이 작업은 일반적으로 Repository 클래스의 init() 메서드에서 실행됩니다.

Configuration 클래스에는 구성에서 다양한 데이터 유형을 가져오기 위한 여러 메서드가 있습니다. 각 메서드는 ConfigValue 객체를 반환합니다. 그런 다음 ConfigValue 객체의 get() 메서드를 사용하여 실제 값을 검색합니다. FullTraversalSample의 다음 스니펫은 Configuration 객체에서 단일 맞춤 정수 값을 검색하는 방법을 보여줍니다.

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

여러 값이 포함된 매개변수를 가져오고 파싱하려면 Configuration 클래스의 유형 파서 중 하나를 사용하여 데이터를 개별 청크로 파싱합니다. 튜토리얼 커넥터의 다음 스니펫은 getMultiValue 메서드를 사용하여 GitHub 저장소 이름 목록을 가져옵니다.

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

전체 순회 수행

전체 순회를 수행하고 저장소의 색인을 생성하려면 getAllDocs()를 재정의합니다. getAllDocs() 메서드는 체크포인트를 받습니다. 체크포인트는 프로세스가 중단되었을 때 특정 항목에서 색인 생성을 계속하는 데 사용됩니다. 저장소의 각 항목에 대해 getAllDocs() 메서드에서 다음 단계를 실행합니다.

  1. 권한을 설정합니다.
  2. 색인을 생성할 항목의 메타데이터를 설정합니다.
  3. 메타데이터와 항목을 색인 생성이 가능한 하나의 RepositoryDoc로 결합합니다.
  4. 색인 생성이 가능한 각 항목을 getAllDocs() 메서드에서 반환하는 반복자에 패키징합니다. getAllDocs()는 실제로 ApiOperation 객체의 반복인 CheckpointCloseableIterable를 반환하며, 각 객체는 RepositoryDoc에서 실행된 API 요청(예: 색인 생성)을 나타냅니다.

항목 집합이 너무 커서 단일 호출로 처리할 수 없으면 체크포인트를 포함하고 hasMore(true)를 설정하여 색인 생성에 더 많은 항목을 사용할 수 있음을 나타냅니다.

항목에 대한 권한 설정

저장소는 액세스제어 목록(ACL)을 사용하여 항목 액세스 권한이 있는 사용자 또는 그룹을 식별합니다. ACL은 항목에 액세스할 수 있는 그룹 또는 사용자의 ID 목록입니다.

항목에 액세스할 수 있는 사용자만 검색결과에서 해당 항목을 볼 수 있도록 하려면 저장소에서 사용한 ACL을 복제해야 합니다. Google Cloud Search가 항목에 대한 올바른 액세스 수준을 제공하는 데 필요한 정보를 사용할 수 있도록 항목의 색인을 생성할 때 항목의 ACL을 포함해야 합니다.

콘텐츠 커넥터 SDK는 대부분의 저장소의 ACL을 모델링하기 위한 다양한 ACL 클래스와 메소드 집합을 제공합니다. 항목의 색인을 생성할 때 저장소의 각 항목에 대한 ACL을 분석하고 Google Cloud Search에 해당하는 ACL을 만들어야 합니다. 저장소의 ACL이 ACL 상속과 같은 개념을 사용하면 ACL을 모델링하기가 어려울 수 있습니다. Google Cloud Search ACL에 대한 자세한 내용은 Google Cloud Search ACL을 참조하세요.

참고: Cloud Search Indexing API는 단일 도메인 ACL은 지원하지만 도메인 간 ACL은 지원하지 않습니다. Acl.Builder 클래스를 사용하여 ACL을 사용하여 각 항목에 대한 액세스 권한을 설정합니다. 전체 순회 샘플에서 가져온 다음 코드 스니펫을 사용하면 검색을 실행할 때 모든 사용자 또는 '주 구성원'(getCustomerPrincipal())이 모든 항목의 '리더'(.setReaders())가 될 수 있습니다.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

저장소의 ACL을 적절하게 모델링하려면 ACL을 이해해야 합니다. 예를 들어 일종의 상속 모델을 사용하는 파일 시스템 안에서 파일의 색인을 생성하여 하위 폴더가 상위 폴더로부터 권한을 상속하도록 할 수 있습니다. ACL 상속을 모델링하려면 Google Cloud Search ACL에서 설명하는 추가 정보가 필요합니다.

항목의 메타데이터 설정

메타데이터는 Item 객체에 저장됩니다. Item를 만들려면 최소한 항목의 고유한 문자열 ID, 항목 유형, ACL, URL, 버전이 필요합니다. 다음 코드 스니펫은 IndexingItemBuilder 도우미 클래스를 사용하여 Item를 빌드하는 방법을 보여줍니다.

FullTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Using the SDK item builder class to create the document with appropriate attributes
// (this can be expanded to include metadata fields etc.)
Item item = IndexingItemBuilder.fromConfiguration(Integer.toString(id))
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .build();

색인 생성이 가능한 항목 만들기

항목의 메타데이터를 설정한 후에는 RepositoryDoc.Builder 클래스를 사용하여 실제 색인 생성이 가능한 항목을 만들 수 있습니다. 다음 예시에서는 색인 생성이 가능한 단일 항목을 만드는 방법을 보여줍니다.

FullTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %d", id);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

// Create the fully formed document
RepositoryDoc doc = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT)
    .build();

RepositoryDoc은 실제 IndexingService.indexItem() 요청을 실행하는 ApiOperation 유형입니다.

RepositoryDoc.Builder 클래스의 setRequestMode() 메서드를 사용하여 색인 생성 요청을 ASYNCHRONOUS 또는 SYNCHRONOUS로 식별할 수도 있습니다.

ASYNCHRONOUS
비동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 길며, 색인 생성 요청의 대규모 처리량 할당량을 수용합니다. 비동기 모드는 전체 저장소의 초기 색인 생성 (백필)에 권장됩니다.
SYNCHRONOUS
동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 짧으며 제한된 처리량 할당량을 수용합니다. 동기 모드는 저장소의 업데이트 또는 변경에 대한 색인 생성에 권장됩니다. 요청 모드를 지정하지 않으면 기본값은 SYNCHRONOUS입니다.

색인 생성 가능한 각 항목을 반복자에 패키징

getAllDocs() 메서드는 RepositoryDoc 객체의 Iterator, 구체적으로 CheckpointCloseableIterable를 반환합니다. CheckpointClosableIterableImpl.Builder 클래스를 사용하여 반복자를 생성하고 반환할 수 있습니다. 다음 코드 스니펫은 반복자를 구성하고 반환하는 방법을 보여줍니다.

FullTraversalSample.java
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(allDocs).build();

SDK는 반복자 안에 포함된 각 색인 생성 호출을 실행합니다.

다음 단계

그 다음으로는 아래와 같은 옵션도 고려해 볼 수 있습니다.

템플릿 클래스를 사용하여 목록 순회 커넥터 만들기

Cloud Search 색인 생성 큐는 저장소의 각 항목에 대한 ID와 선택적 해시 값을 저장하는 데 사용됩니다. 목록 순회 커넥터는 항목 ID를 Google Cloud Search 색인 생성 큐로 푸시하고 색인 생성을 위해 한 번에 하나씩 가져옵니다. Google Cloud Search는 큐를 관리하고 큐 콘텐츠를 비교하여 항목 상태(예: 항목이 저장소에서 삭제되었는지 여부)를 확인합니다. Cloud Search 색인 생성 큐에 대한 자세한 내용은 Cloud Search 색인 생성 큐를 참조하세요.

이 섹션에서는 ListTraversalSample 예시의 코드 스니펫을 참조합니다.

커넥터의 진입점 구현

커넥터의 진입점은 main() 메서드입니다. 이 메서드의 기본 작업은 Application 클래스의 인스턴스를 만들고 start() 메서드를 호출하여 커넥터를 실행하는 것입니다.

application.start()를 호출하기 전에 IndexingApplication.Builder 클래스를 사용하여 ListingConnector 템플릿을 인스턴스화합니다. ListingConnector는 메서드를 구현하는 Repository 객체를 허용합니다. 다음 스니펫은 ListingConnector 및 연결된 Repository를 인스턴스화하는 방법을 보여줍니다.

ListTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a
 * list traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new ListingConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

내부적으로 SDK는 커넥터의 main() 메서드가 Application.build를 호출한 후 initConfig() 메서드를 호출합니다. initConfig() 메서드:

  1. Configuation.isInitialized() 메서드를 호출하여 Configuration가 초기화되지 않았는지 확인합니다.
  2. Google에서 제공하는 키-값 쌍을 사용하여 Configuration 객체를 초기화합니다. 각 키-값 쌍은 Configuration 객체 내 ConfigValue 객체에 저장됩니다.

Repository 인터페이스 구현

Repository 객체의 유일한 목적은 저장소 항목의 순회와 색인 생성을 수행하는 것입니다. 템플릿을 사용하는 경우 콘텐츠 커넥터를 만들려면 Repository 인터페이스 내에서 특정 메서드를 재정의하기만 하면 됩니다. 재정의할 메서드는 사용하는 템플릿과 순회 전략에 따라 다릅니다. ListingConnector의 경우 다음 메서드를 재정의합니다.

  • init() 메서드 데이터 저장소 설정 및 초기화를 실행하려면 init() 메서드를 재정의합니다.

  • getIds() 메서드 저장소에 있는 모든 레코드의 ID와 해시 값을 검색하려면 getIds() 메서드를 재정의합니다.

  • getDoc() 메서드 색인에서 항목을 새로 추가, 업데이트, 수정 또는 삭제하려면 getDoc() 메서드를 재정의합니다.

  • (선택사항) getChanges() 메서드. 저장소가 변경 감지를 지원하면 getChanges() 메서드를 재정의합니다. 이 메소드는 수정된 항목을 검색하고 그 색인을 생성하기 위해 (구성에 정의된 대로) 예약된 증분 순환마다 한 번씩 호출됩니다.

  • (선택사항) close() 메서드. 저장소 정리를 수행해야 하면 close() 메서드를 재정의합니다. 이 메서드는 커넥터 종료 시 한 번 호출됩니다.

Repository 객체의 각 메서드는 ApiOperation 객체의 일부 유형을 반환합니다. ApiOperation 객체는 저장소의 실제 색인 생성을 수행하기 위해 단일 호출 또는 다중 IndexingService.indexItem() 호출의 형태로 작업을 실행합니다.

커스텀 구성 매개변수 가져오기

커넥터 구성을 처리하려면 Configuration 객체에서 커스텀 매개변수를 가져와야 합니다. 이 작업은 일반적으로 Repository 클래스의 init() 메서드에서 실행됩니다.

Configuration 클래스에는 구성에서 다양한 데이터 유형을 가져오기 위한 여러 메서드가 있습니다. 각 메서드는 ConfigValue 객체를 반환합니다. 그런 다음 ConfigValue 객체의 get() 메서드를 사용하여 실제 값을 검색합니다. FullTraversalSample의 다음 스니펫은 Configuration 객체에서 단일 맞춤 정수 값을 검색하는 방법을 보여줍니다.

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

여러 값이 포함된 매개변수를 가져오고 파싱하려면 Configuration 클래스의 유형 파서 중 하나를 사용하여 데이터를 개별 청크로 파싱합니다. 튜토리얼 커넥터의 다음 스니펫은 getMultiValue 메서드를 사용하여 GitHub 저장소 이름 목록을 가져옵니다.

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

목록 순회 수행

저장소에 있는 모든 레코드의 ID와 해시 값을 검색하려면 getIds() 메서드를 재정의합니다. getIds() 메서드는 체크포인트를 받습니다. 체크포인트는 프로세스가 중단되었을 때 특정 항목에서 색인 생성을 계속하는 데 사용됩니다.

그런 다음 Cloud Search 색인 생성 큐의 각 항목을 처리하도록 getDoc() 메서드를 재정의합니다.

항목 ID 및 해시 값 푸시

저장소에서 항목 ID 및 연결된 콘텐츠 해시 값을 가져오려면 getIds()을 재정의합니다. 그러면 ID와 해시 값 쌍이 Cloud Search 색인 생성 큐에 대한 푸시 작업 요청으로 패키징됩니다. 일반적으로 루트 또는 상위 ID가 먼저 푸시된 다음 항목의 전체 계층구조가 처리될 때까지 하위 ID가 푸시됩니다.

getIds() 메서드는 색인을 생성할 마지막 항목을 나타내는 체크포인트를 받습니다. 프로세스가 중단되었을 때 특정 항목에서 색인 생성을 계속하는 데 체크포인트를 사용할 수 있습니다. 저장소의 각 항목에 대해 getIds() 메서드에서 다음 단계를 수행합니다.

  • 저장소에서 각 항목 ID와 연결된 해시 값을 가져옵니다.
  • 각 ID와 해시 값의 쌍을 PushItems로 패키징합니다.
  • PushItemsgetIds() 메서드에서 반환하는 반복자로 결합합니다. getIds()는 실제로 ApiOperation 객체의 반복인 CheckpointCloseableIterable를 반환합니다. 각 객체는 RepositoryDoc에서 실행된 API 요청(예: 항목을 큐로 푸시)을 나타냅니다.

다음 코드 스니펫은 각 항목 ID와 해시 값을 가져와서 PushItems에 삽입하는 방법을 보여줍니다. PushItems는 항목을 Cloud Search 색인 생성 큐로 푸시하는 ApiOperation 요청입니다.

ListTraversalSample.java
PushItems.Builder allIds = new PushItems.Builder();
for (Map.Entry<Integer, Long> entry : this.documents.entrySet()) {
  String documentId = Integer.toString(entry.getKey());
  String hash = this.calculateMetadataHash(entry.getKey());
  PushItem item = new PushItem().setMetadataHash(hash);
  log.info("Pushing " + documentId);
  allIds.addPushItem(documentId, item);
}

다음 코드 스니펫은 PushItems.Builder 클래스를 사용하여 ID와 해시 값을 단일 푸시 ApiOperation로 패키징하는 방법을 보여줍니다.

ListTraversalSample.java
ApiOperation pushOperation = allIds.build();
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(
      Collections.singletonList(pushOperation))
  .build();
return iterator;

항목이 추가 처리를 위해 Cloud Search 색인 생성 큐로 푸시됩니다.

각 항목 검색 및 처리

Cloud Search 색인 생성 큐의 각 항목을 처리하려면 getDoc()를 재정의합니다. 항목의 종류에는 신규 또는 수정 항목, 변경되지 않았거나 더 이상 소스 저장소에 존재하지 않는 항목이 있습니다. 새로운 또는 수정된 각 항목을 검색하고 색인을 만드세요. 소스 저장소에 더 이상 존재하지 않는 항목은 색인에서 삭제하세요.

getDoc() 메서드는 Google Cloud Search 색인 생성 큐에서 항목을 받습니다. 큐의 각 항목에 대해 getDoc() 메서드에서 다음 단계를 수행합니다.

  1. Cloud Search 색인 생성 큐 내에서 항목의 ID가 저장소에 존재하는지 확인합니다. 존재하지 않으면 색인에서 항목을 삭제합니다.

  2. 항목 상태에 대한 색인을 폴링하고 항목이 변경되지 않은 경우(ACCEPTED)에는 아무 것도 하지 않습니다.

  3. 색인이 변경되거나 새로운 항목인 경우:

    1. 권한을 설정합니다.
    2. 색인을 생성할 항목의 메타데이터를 설정합니다.
    3. 메타데이터와 항목을 색인 생성이 가능한 하나의 RepositoryDoc로 결합합니다.
    4. RepositoryDoc를 반환합니다.

참고: ListingConnector 템플릿은 getDoc() 메서드에서 null 반환을 지원하지 않습니다. null를 반환하면 NullPointerException.이 반환됩니다.

삭제된 항목 처리

다음 코드 스니펫은 항목이 저장소에 있는지 확인하고, 없으면 항목을 삭제합니다.

ListTraversalSample.java
String resourceName = item.getName();
int documentId = Integer.parseInt(resourceName);

if (!documents.containsKey(documentId)) {
  // Document no longer exists -- delete it
  log.info(() -> String.format("Deleting document %s", item.getName()));
  return ApiOperations.deleteItem(resourceName);
}

documents는 저장소를 나타내는 데이터 구조입니다. documents에서 documentID를 찾을 수 없으면 APIOperations.deleteItem(resourceName)를 반환하여 색인에서 항목을 삭제합니다.

변경되지 않은 항목 처리

다음 코드 스니펫은 Cloud Search 색인 생성 큐의 항목 상태를 폴링하고 변경되지 않은 항목을 처리하는 방법을 보여줍니다.

ListTraversalSample.java
String currentHash = this.calculateMetadataHash(documentId);
if (this.canSkipIndexing(item, currentHash)) {
  // Document neither modified nor deleted, ack the push
  log.info(() -> String.format("Document %s not modified", item.getName()));
  PushItem pushItem = new PushItem().setType("NOT_MODIFIED");
  return new PushItems.Builder().addPushItem(resourceName, pushItem).build();
}

항목이 수정되지 않았는지 확인하려면 항목의 상태와 함께 변경을 나타낼 수 있는 다른 메타데이터를 확인하세요. 이 예시에서는 항목이 변경되었는지 확인하기 위해 메타데이터 해시가 사용되었습니다.

ListTraversalSample.java
/**
 * Checks to see if an item is already up to date
 *
 * @param previousItem Polled item
 * @param currentHash  Metadata hash of the current github object
 * @return PushItem operation
 */
private boolean canSkipIndexing(Item previousItem, String currentHash) {
  if (previousItem.getStatus() == null || previousItem.getMetadata() == null) {
    return false;
  }
  String status = previousItem.getStatus().getCode();
  String previousHash = previousItem.getMetadata().getHash();
  return "ACCEPTED".equals(status)
      && previousHash != null
      && previousHash.equals(currentHash);
}

항목에 대한 권한 설정

저장소는 액세스제어 목록(ACL)을 사용하여 항목 액세스 권한이 있는 사용자 또는 그룹을 식별합니다. ACL은 항목에 액세스할 수 있는 그룹 또는 사용자의 ID 목록입니다.

항목에 액세스할 수 있는 사용자만 검색결과에서 해당 항목을 볼 수 있도록 하려면 저장소에서 사용한 ACL을 복제해야 합니다. Google Cloud Search가 항목에 대한 올바른 액세스 수준을 제공하는 데 필요한 정보를 사용할 수 있도록 항목의 색인을 생성할 때 항목의 ACL을 포함해야 합니다.

콘텐츠 커넥터 SDK는 대부분의 저장소의 ACL을 모델링하기 위한 다양한 ACL 클래스와 메소드 집합을 제공합니다. 항목의 색인을 생성할 때 저장소의 각 항목에 대한 ACL을 분석하고 Google Cloud Search에 해당하는 ACL을 만들어야 합니다. 저장소의 ACL이 ACL 상속과 같은 개념을 사용하면 ACL을 모델링하기가 어려울 수 있습니다. Google Cloud Search ACL에 대한 자세한 내용은 Google Cloud Search ACL을 참조하세요.

참고: Cloud Search Indexing API는 단일 도메인 ACL은 지원하지만 도메인 간 ACL은 지원하지 않습니다. Acl.Builder 클래스를 사용하여 ACL을 사용하여 각 항목에 대한 액세스 권한을 설정합니다. 전체 순회 샘플에서 가져온 다음 코드 스니펫을 사용하면 검색을 실행할 때 모든 사용자 또는 '주 구성원'(getCustomerPrincipal())이 모든 항목의 '리더'(.setReaders())가 될 수 있습니다.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

저장소의 ACL을 적절하게 모델링하려면 ACL을 이해해야 합니다. 예를 들어 일종의 상속 모델을 사용하는 파일 시스템 안에서 파일의 색인을 생성하여 하위 폴더가 상위 폴더로부터 권한을 상속하도록 할 수 있습니다. ACL 상속을 모델링하려면 Google Cloud Search ACL에서 설명하는 추가 정보가 필요합니다.

항목의 메타데이터 설정

메타데이터는 Item 객체에 저장됩니다. Item를 만들려면 최소한 항목의 고유한 문자열 ID, 항목 유형, ACL, URL, 버전이 필요합니다. 다음 코드 스니펫은 IndexingItemBuilder 도우미 클래스를 사용하여 Item를 빌드하는 방법을 보여줍니다.

ListTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Set metadata hash so queue can detect changes
String metadataHash = this.calculateMetadataHash(documentId);

// Using the SDK item builder class to create the document with
// appropriate attributes. This can be expanded to include metadata
// fields etc.
Item item = IndexingItemBuilder.fromConfiguration(Integer.toString(documentId))
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .setHash(metadataHash)
    .build();

색인 생성이 가능한 항목 만들기

항목의 메타데이터를 설정한 후에는 RepositoryDoc.Builder를 사용하여 실제 색인 생성이 가능한 항목을 만들 수 있습니다. 다음 예시에서는 색인 생성이 가능한 단일 항목을 만드는 방법을 보여줍니다.

ListTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %d", documentId);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

// Create the fully formed document
RepositoryDoc doc = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT)
    .build();

RepositoryDoc은 실제 IndexingService.indexItem() 요청을 실행하는 ApiOperation 유형입니다.

RepositoryDoc.Builder 클래스의 setRequestMode() 메서드를 사용하여 색인 생성 요청을 ASYNCHRONOUS 또는 SYNCHRONOUS로 식별할 수도 있습니다.

ASYNCHRONOUS
비동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 길며, 색인 생성 요청의 대규모 처리량 할당량을 수용합니다. 비동기 모드는 전체 저장소의 초기 색인 생성 (백필)에 권장됩니다.
SYNCHRONOUS
동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 짧으며 제한된 처리량 할당량을 수용합니다. 동기 모드는 저장소의 업데이트 또는 변경에 대한 색인 생성에 권장됩니다. 요청 모드를 지정하지 않으면 기본값은 SYNCHRONOUS입니다.

다음 단계

그 다음으로는 아래와 같은 옵션도 고려해 볼 수 있습니다.

  • (선택사항) close() 메서드를 구현하여 종료 전에 리소스를 해제합니다.
  • (선택사항) 콘텐츠 커넥터 SDK를 사용하여 ID 커넥터를 만듭니다.

템플릿 클래스를 사용하여 그래프 순회 커넥터 만들기

Cloud Search 색인 생성 큐는 저장소의 각 항목에 대한 ID와 선택적 해시 값을 저장하는 데 사용됩니다. 그래프 순회 커넥터는 항목 ID를 Google Cloud Search 색인 생성 큐로 푸시하고 색인 생성을 위해 한 번에 하나씩 가져옵니다. Google Cloud Search는 큐를 관리하고 큐 콘텐츠를 비교하여 항목 상태(예: 항목이 저장소에서 삭제되었는지 여부)를 확인합니다. Cloud Search 색인 생성 큐에 대한 자세한 내용은 Google Cloud Search 색인 생성 큐를 참조하세요.

색인을 생성하는 동안 데이터 저장소에서 항목 콘텐츠를 가져오고 하위 항목 ID가 큐로 푸시됩니다. 커넥터는 모든 항목이 처리될 때까지 상위 및 하위 ID를 반복적으로 처리합니다.

이 섹션에서는 GraphTraversalSample 예시의 코드 스니펫을 참조합니다.

커넥터의 진입점 구현

커넥터의 진입점은 main() 메서드입니다. 이 메서드의 기본 작업은 Application 클래스의 인스턴스를 만들고 start() 메서드를 호출하여 커넥터를 실행하는 것입니다.

application.start()를 호출하기 전에 IndexingApplication.Builder 클래스를 사용하여 ListingConnector 템플릿을 인스턴스화합니다. ListingConnector는 메서드를 구현하는 Repository 객체를 허용합니다.

다음 스니펫은 ListingConnector 및 연결된 Repository를 인스턴스화하는 방법을 보여줍니다.

GraphTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a graph
 * traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new ListingConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

내부적으로 SDK는 커넥터의 main() 메서드가 Application.build를 호출한 후 initConfig() 메서드를 호출합니다. initConfig() 메서드:

  1. Configuation.isInitialized() 메서드를 호출하여 Configuration가 초기화되지 않았는지 확인합니다.
  2. Google에서 제공하는 키-값 쌍을 사용하여 Configuration 객체를 초기화합니다. 각 키-값 쌍은 Configuration 객체 내 ConfigValue 객체에 저장됩니다.

Repository 인터페이스 구현

Repository 객체의 유일한 목적은 저장소 항목의 순회와 색인 생성을 수행하는 것입니다. 템플릿을 사용하는 경우 콘텐츠 커넥터를 만들려면 Repository 인터페이스 내에서 특정 메서드를 재정의하기만 하면 됩니다. 재정의할 메소드는 사용하는 템플릿과 순회 전략에 따라 다릅니다. ListingConnector의 경우 다음 메서드를 재정의합니다.

  • init() 메서드 데이터 저장소 설정 및 초기화를 실행하려면 init() 메서드를 재정의합니다.

  • getIds() 메서드 저장소에 있는 모든 레코드의 ID와 해시 값을 검색하려면 getIds() 메서드를 재정의합니다.

  • getDoc() 메서드 색인에서 항목을 새로 추가, 업데이트, 수정 또는 삭제하려면 getDoc() 메서드를 재정의합니다.

  • (선택사항) getChanges() 메서드. 저장소가 변경 감지를 지원하면 getChanges() 메서드를 재정의합니다. 이 메소드는 수정된 항목을 검색하고 그 색인을 생성하기 위해 (구성에 정의된 대로) 예약된 증분 순환마다 한 번씩 호출됩니다.

  • (선택사항) close() 메서드. 저장소 정리를 수행해야 하면 close() 메서드를 재정의합니다. 이 메서드는 커넥터 종료 시 한 번 호출됩니다.

Repository 객체의 각 메서드는 ApiOperation 객체의 일부 유형을 반환합니다. ApiOperation 객체는 저장소의 실제 색인 생성을 수행하기 위해 단일 호출 또는 다중 IndexingService.indexItem() 호출의 형태로 작업을 실행합니다.

커스텀 구성 매개변수 가져오기

커넥터 구성을 처리하려면 Configuration 객체에서 커스텀 매개변수를 가져와야 합니다. 이 작업은 일반적으로 Repository 클래스의 init() 메서드에서 실행됩니다.

Configuration 클래스에는 구성에서 다양한 데이터 유형을 가져오기 위한 여러 메서드가 있습니다. 각 메서드는 ConfigValue 객체를 반환합니다. 그런 다음 ConfigValue 객체의 get() 메서드를 사용하여 실제 값을 검색합니다. FullTraversalSample의 다음 스니펫은 Configuration 객체에서 단일 맞춤 정수 값을 검색하는 방법을 보여줍니다.

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

여러 값이 포함된 매개변수를 가져오고 파싱하려면 Configuration 클래스의 유형 파서 중 하나를 사용하여 데이터를 개별 청크로 파싱합니다. 튜토리얼 커넥터의 다음 스니펫은 getMultiValue 메서드를 사용하여 GitHub 저장소 이름 목록을 가져옵니다.

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

그래프 순회 수행

저장소에 있는 모든 레코드의 ID와 해시 값을 검색하려면 getIds() 메서드를 재정의합니다. getIds() 메서드는 체크포인트를 받습니다. 체크포인트는 프로세스가 중단되었을 때 특정 항목에서 색인 생성을 계속하는 데 사용됩니다.

그런 다음 Cloud Search 색인 생성 큐의 각 항목을 처리하도록 getDoc() 메서드를 재정의합니다.

항목 ID 및 해시 값 푸시

저장소에서 항목 ID 및 연결된 콘텐츠 해시 값을 가져오려면 getIds()을 재정의합니다. 그러면 ID와 해시 값 쌍이 Cloud Search 색인 생성 큐에 대한 푸시 작업 요청으로 패키징됩니다. 일반적으로 루트 또는 상위 ID가 먼저 푸시된 다음 항목의 전체 계층구조가 처리될 때까지 하위 ID가 푸시됩니다.

getIds() 메서드는 색인을 생성할 마지막 항목을 나타내는 체크포인트를 받습니다. 프로세스가 중단되었을 때 특정 항목에서 색인 생성을 계속하는 데 체크포인트를 사용할 수 있습니다. 저장소의 각 항목에 대해 getIds() 메서드에서 다음 단계를 수행합니다.

  • 저장소에서 각 항목 ID와 연결된 해시 값을 가져옵니다.
  • 각 ID와 해시 값의 쌍을 PushItems로 패키징합니다.
  • PushItemsgetIds() 메서드에서 반환하는 반복자로 결합합니다. getIds()는 실제로 ApiOperation 객체의 반복인 CheckpointCloseableIterable를 반환합니다. 각 객체는 RepositoryDoc에서 실행된 API 요청(예: 항목을 큐로 푸시)을 나타냅니다.

다음 코드 스니펫은 각 항목 ID와 해시 값을 가져와서 PushItems에 삽입하는 방법을 보여줍니다. PushItems는 항목을 Cloud Search 색인 생성 큐로 푸시하는 ApiOperation 요청입니다.

GraphTraversalSample.java
PushItems.Builder allIds = new PushItems.Builder();
PushItem item = new PushItem();
allIds.addPushItem("root", item);

다음 코드 스니펫은 PushItems.Builder 클래스를 사용하여 ID와 해시 값을 단일 푸시 ApiOperation로 패키징하는 방법을 보여줍니다.

GraphTraversalSample.java
ApiOperation pushOperation = allIds.build();
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(
      Collections.singletonList(pushOperation))
  .build();

항목이 추가 처리를 위해 Cloud Search 색인 생성 큐로 푸시됩니다.

각 항목 검색 및 처리

Cloud Search 색인 생성 큐의 각 항목을 처리하려면 getDoc()를 재정의합니다. 항목의 종류에는 신규 또는 수정 항목, 변경되지 않았거나 더 이상 소스 저장소에 존재하지 않는 항목이 있습니다. 새로운 또는 수정된 각 항목을 검색하고 색인을 만드세요. 소스 저장소에 더 이상 존재하지 않는 항목은 색인에서 삭제하세요.

getDoc() 메서드는 Cloud Search 색인 생성 큐에서 항목을 받습니다. 큐의 각 항목에 대해 getDoc() 메서드에서 다음 단계를 수행합니다.

  1. Cloud Search 색인 생성 큐 내에서 항목의 ID가 저장소에 존재하는지 확인합니다. 존재하지 않으면 색인에서 항목을 삭제합니다. 항목이 존재하면 다음 단계를 계속 진행합니다.

  2. 색인이 변경되거나 새로운 항목인 경우:

    1. 권한을 설정합니다.
    2. 색인을 생성할 항목의 메타데이터를 설정합니다.
    3. 메타데이터와 항목을 색인 생성이 가능한 하나의 RepositoryDoc로 결합합니다.
    4. 추가 처리를 위해 하위 ID를 Cloud Search 색인 생성 큐에 배치합니다.
    5. RepositoryDoc를 반환합니다.

삭제된 항목 처리

다음 코드 스니펫은 항목이 색인에 있는지 확인하고, 없으면 항목을 삭제합니다.

GraphTraversalSample.java
String resourceName = item.getName();
if (documentExists(resourceName)) {
  return buildDocumentAndChildren(resourceName);
}
// Document doesn't exist, delete it
log.info(() -> String.format("Deleting document %s", resourceName));
return ApiOperations.deleteItem(resourceName);

항목에 대한 권한 설정

저장소는 액세스제어 목록(ACL)을 사용하여 항목 액세스 권한이 있는 사용자 또는 그룹을 식별합니다. ACL은 항목에 액세스할 수 있는 그룹 또는 사용자의 ID 목록입니다.

항목에 액세스할 수 있는 사용자만 검색결과에서 해당 항목을 볼 수 있도록 하려면 저장소에서 사용한 ACL을 복제해야 합니다. Google Cloud Search가 항목에 대한 올바른 액세스 수준을 제공하는 데 필요한 정보를 사용할 수 있도록 항목의 색인을 생성할 때 항목의 ACL을 포함해야 합니다.

콘텐츠 커넥터 SDK는 대부분의 저장소의 ACL을 모델링하기 위한 다양한 ACL 클래스와 메소드 집합을 제공합니다. 항목의 색인을 생성할 때 저장소의 각 항목에 대한 ACL을 분석하고 Google Cloud Search에 해당하는 ACL을 만들어야 합니다. 저장소의 ACL이 ACL 상속과 같은 개념을 사용하면 ACL을 모델링하기가 어려울 수 있습니다. Google Cloud Search ACL에 대한 자세한 내용은 Google Cloud Search ACL을 참조하세요.

참고: Cloud Search Indexing API는 단일 도메인 ACL은 지원하지만 도메인 간 ACL은 지원하지 않습니다. Acl.Builder 클래스를 사용하여 ACL을 사용하여 각 항목에 대한 액세스 권한을 설정합니다. 전체 순회 샘플에서 가져온 다음 코드 스니펫을 사용하면 검색을 실행할 때 모든 사용자 또는 '주 구성원'(getCustomerPrincipal())이 모든 항목의 '리더'(.setReaders())가 될 수 있습니다.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

저장소의 ACL을 적절하게 모델링하려면 ACL을 이해해야 합니다. 예를 들어 일종의 상속 모델을 사용하는 파일 시스템 안에서 파일의 색인을 생성하여 하위 폴더가 상위 폴더로부터 권한을 상속하도록 할 수 있습니다. ACL 상속을 모델링하려면 Google Cloud Search ACL에서 설명하는 추가 정보가 필요합니다.

항목의 메타데이터 설정

메타데이터는 Item 객체에 저장됩니다. Item를 만들려면 최소한 항목의 고유한 문자열 ID, 항목 유형, ACL, URL, 버전이 필요합니다. 다음 코드 스니펫은 IndexingItemBuilder 도우미 클래스를 사용하여 Item를 빌드하는 방법을 보여줍니다.

GraphTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Using the SDK item builder class to create the document with
// appropriate attributes. This can be expanded to include metadata
// fields etc.
Item item = IndexingItemBuilder.fromConfiguration(documentId)
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .build();

색인 생성이 가능한 항목 만들기

항목의 메타데이터를 설정한 후에는 RepositoryDoc.Builder를 사용하여 실제 색인 생성이 가능한 항목을 만들 수 있습니다. 다음 예시에서는 색인 생성이 가능한 단일 항목을 만드는 방법을 보여줍니다.

GraphTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %s", documentId);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

RepositoryDoc.Builder docBuilder = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT);

RepositoryDoc은 실제 IndexingService.indexItem() 요청을 실행하는 ApiOperation 유형입니다.

RepositoryDoc.Builder 클래스의 setRequestMode() 메서드를 사용하여 색인 생성 요청을 ASYNCHRONOUS 또는 SYNCHRONOUS로 식별할 수도 있습니다.

ASYNCHRONOUS
비동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 길며, 색인 생성 요청의 대규모 처리량 할당량을 수용합니다. 비동기 모드는 전체 저장소의 초기 색인 생성 (백필)에 권장됩니다.
SYNCHRONOUS
동기 모드는 색인 생성에서 제공까지의 지연 시간이 더 짧으며 제한된 처리량 할당량을 수용합니다. 동기 모드는 저장소의 업데이트 또는 변경에 대한 색인 생성에 권장됩니다. 요청 모드를 지정하지 않으면 기본값은 SYNCHRONOUS입니다.

하위 ID를 Cloud Search 색인 생성 큐에 배치

다음 코드 스니펫은 현재 처리 중인 상위 항목의 하위 ID를 처리를 위한 큐에 포함하는 방법을 보여줍니다. 이들 ID는 상위 항목의 색인이 생성된 후에 처리됩니다.

GraphTraversalSample.java
// Queue the child nodes to visit after indexing this document
Set<String> childIds = getChildItemNames(documentId);
for (String id : childIds) {
  log.info(() -> String.format("Pushing child node %s", id));
  PushItem pushItem = new PushItem();
  docBuilder.addChildId(id, pushItem);
}

RepositoryDoc doc = docBuilder.build();

다음 단계

그 다음으로는 아래와 같은 옵션도 고려해 볼 수 있습니다.

  • (선택사항) close() 메서드를 구현하여 종료 전에 리소스를 해제합니다.
  • (선택사항) ID 커넥터 SDK를 사용하여 ID 커넥터를 생성합니다.

REST API를 사용하여 콘텐츠 커넥터 만들기

다음 섹션에서는 REST API를 사용하여 콘텐츠 커넥터를 만드는 방법을 설명합니다.

순회 전략 결정

콘텐츠 커넥터의 기본 기능은 저장소를 순회하고 데이터의 색인을 생성하는 것입니다. 저장소의 데이터 크기와 레이아웃을 기준으로 순회 전략을 구현해야 합니다. 다음은 일반적인 3가지 순회 전략입니다.

전체 순회 전략

전체 순회 전략은 전체 저장소를 검사하여 무조건 모든 항목의 색인을 생성합니다. 이 전략은 일반적으로 저장소가 작고, 색인을 생성할 때마다 전체 순회를 수행하는 오버헤드를 감당할 수 있는 경우에 사용됩니다.

이 순회 전략은 주로 정적, 비계층적 데이터가 있는 소규모 저장소에 적합합니다. 변경 감지가 어렵거나 저장소에서 지원되지 않는 경우에도 이 순회 전략을 사용할 수 있습니다.

목록 순회 전략

목록 순회 전략은 모든 하위 노드를 포함한 전체 저장소를 검사하여 각 항목의 상태를 확인합니다. 그런 다음 커넥터가 두 번째 순회를 수행하여 새로운 항목 또는 마지막 색인 생성 후에 업데이트된 항목만 색인을 생성합니다. 이 전략은 색인을 업데이트할 때마다 전체 순회를 수행하는 대신 기존 색인에 증분 업데이트를 수행하기 위해 일반적으로 사용됩니다.

이 순회 전략은 변경 감지가 어렵거나 저장소에서 지원되지 않는 경우, 비계층적 데이터가 있는 경우, 아주 큰 데이터 세트를 사용하는 경우에 적합합니다.

그래프 순회

그래프 순회 전략은 전체 상위 노드를 검사하여 각 항목의 상태를 확인합니다. 그런 다음 커넥터가 두 번째 순회를 수행하여 새로운 루트 노드의 항목 또는 마지막 색인 생성 후에 업데이트된 항목에 대해서만 색인을 생성합니다. 마지막으로 커넥터는 모든 하위 ID를 전달한 다음 새로운 또는 업데이트된 하위 노드의 항목에 대하여 색인을 생성합니다. 커넥터는 모든 항목이 처리될 때까지 모든 하위 노드를 반복적으로 계속 순회합니다. 이러한 순회는 일반적으로 모든 ID를 나열하는 방법이 실용적이지 않은 계층 구조의 저장소에 사용됩니다.

이 전략은 일련의 디렉토리 또는 웹 페이지와 같이 크롤링해야 하는 계층적 데이터가 있는 경우에 적합합니다.

순회 전략 구현 및 항목의 색인 생성

Cloud Search에서 색인을 생성할 수 있는 모든 요소를 Cloud Search API에서는 항목이라고 합니다. 항목은 파일, 폴더, CSV 파일의 행 또는 데이터베이스 레코드일 수 있습니다.

스키마가 등록된 후에 다음과 같은 방법으로 색인을 채울 수 있습니다.

  1. (선택사항) 색인 생성을 위해 100KiB보다 큰 파일을 업로드하려면 items.upload를 사용합니다. 크기가 작은 파일의 경우 items.index를 사용하여 콘텐츠를 inlineContent로 삽입합니다.

  2. (선택사항) 색인 생성을 위해 미디어 파일을 업로드하는 데 media.upload를 사용합니다.

  3. items.index를 사용하여 항목의 색인을 생성합니다. 예를 들어 스키마가 영화 스키마의 객체 정의를 사용하는 경우 단일 항목의 색인 생성 요청은 다음과 같습니다.

    {
      "name": "datasource/<data_source_id>/items/titanic",
      "acl": {
        "readers": [
          {
            "gsuitePrincipal": {
              "gsuiteDomain": true
            }
          }
        ]
      },
      "metadata": {
        "title": "Titanic",
        "viewUrl": "http://www.imdb.com/title/tt2234155/?ref_=nv_sr_1",
        "objectType": "movie"
      },
      "structuredData": {
        "object": {
          "properties": [
            {
              "name": "movieTitle",
              "textValues": {
                "values": [
                  "Titanic"
                ]
              }
            },
            {
              "name": "releaseDate",
              "dateValues": {
                "values": [
                  {
                    "year": 1997,
                    "month": 12,
                    "day": 19
                  }
                ]
              }
            },
            {
              "name": "actorName",
              "textValues": {
                "values": [
                  "Leonardo DiCaprio",
                  "Kate Winslet",
                  "Billy Zane"
                ]
              }
            },
            {
              "name": "genre",
              "enumValues": {
                "values": [
                  "Drama",
                  "Action"
                ]
              }
            },
            {
              "name": "userRating",
              "integerValues": {
                "values": [
                  8
                ]
              }
            },
            {
              "name": "mpaaRating",
              "textValues": {
                "values": [
                  "PG-13"
                ]
              }
            },
            {
              "name": "duration",
              "textValues": {
                "values": [
                  "3 h 14 min"
                ]
              }
            }
          ]
        }
      },
      "content": {
        "inlineContent": "A seventeen-year-old aristocrat falls in love with a kind but poor artist aboard the luxurious, ill-fated R.M.S. Titanic.",
        "contentFormat": "TEXT"
      },
      "version": "01",
      "itemType": "CONTENT_ITEM"
    }
    
  4. (선택사항) items.get 호출을 사용하여 항목의 색인이 생성되었는지 확인합니다.

전체 순회를 수행하려면 정기적으로 전체 저장소의 색인을 생성합니다. 목록 순회 또는 그래프 순회를 수행하려면 저장소 변경사항을 처리하는 코드를 구현해야 합니다.

저장소 변경사항 처리

주기적으로 저장소에서 각 항목을 수집하고 항목의 색인을 생성하여 전체 색인 생성을 수행할 수 있습니다. 전체 색인 생성은 색인을 최신 상태로 유지하는 데 효과적이지만 규모가 크거나 계층 구조의 저장소를 대상으로 할 때는 비용이 많이 듭니다.

색인 호출을 사용하여 전체 저장소의 색인을 너무 자주 생성하는 대신, 변경사항을 추적하고 변경된 항목만 색인을 생성하기 위한 메커니즘으로 Google Cloud 색인 생성 큐를 사용할 수 있습니다. items.push 요청을 사용하여 항목을 나중에 폴링 및 업데이트할 수 있도록 큐로 푸시할 수 있습니다. Google Cloud 색인 생성 큐에 대한 자세한 내용은 Google Cloud 색인 생성 큐를 참조하세요.

Google Cloud Search API에 대한 자세한 내용은 Cloud Search API를 참조하세요.