Inhaltsconnector erstellen

Ein Inhaltsconnector ist ein Softwareprogramm, mit dem die Daten im Repository eines Unternehmens durchsucht und eine Datenquelle dargestellt wird. Google bietet folgende Optionen zum Entwickeln von Inhalts-Connectors:

Ein typischer Inhaltsconnector führt die folgenden Aufgaben aus:

  1. Konfigurationsparameter lesen und verarbeiten.
  2. Diskrete Teile indexierbarer Daten, sogenannte Elemente, aus dem Inhalts-Repository eines Drittanbieters abrufen.
  3. ACLs, Metadaten und Inhaltsdaten werden in indexierbaren Elementen kombiniert.
  4. Indexiert Elemente in der Cloud Search-Datenquelle.
  5. Optional: Wartet auf Änderungsbenachrichtigungen aus dem Inhalts-Repository des Drittanbieters. Änderungsbenachrichtigungen werden in Indexierungsanfragen umgewandelt, um die Cloud Search-Datenquelle mit dem Repository des Drittanbieters synchron zu halten. Der Connector führt diese Aufgabe nur aus, wenn das Repository die Änderungserkennung unterstützt.

Inhaltsconnectors mit dem Content Connector SDK erstellen

In den folgenden Abschnitten wird erläutert, wie Sie mit dem Content Connector SDK einen Inhaltsconnector erstellen.

Abhängigkeiten einrichten

Sie müssen bestimmte Abhängigkeiten in Ihre Build-Datei aufnehmen, um das SDK verwenden zu können. Klicken Sie unten auf einen Tab, um die Abhängigkeiten für Ihre Build-Umgebung aufzurufen:

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'

Connector-Konfiguration erstellen

Jeder Connector hat eine Konfigurationsdatei mit Parametern, die vom Connector verwendet werden, z. B. die ID für Ihr Repository. Parameter werden als Schlüssel/Wert-Paare definiert, z. B. api.sourceId=1234567890abcdef.

Das Google Cloud Search SDK enthält mehrere von Google bereitgestellte Konfigurationsparameter, die von allen Connectors verwendet werden. Sie müssen die folgenden von Google bereitgestellten Parameter in Ihrer Konfigurationsdatei deklarieren:

  • Für einen Inhaltsconnector benötigen Sie die Parameter api.sourceId und api.serviceAccountPrivateKeyFile, da diese den Speicherort Ihres Repositorys und des für den Zugriff auf das Repository erforderlichen privaten Schlüssels angeben.
  • Für einen Identitätsconnector benötigen Sie den Parameter api.identitySourceId, da dieser den Speicherort Ihrer externen Identitätsquelle angibt. Wenn Sie Nutzer synchronisieren, müssen Sie auch api.customerId als eindeutige ID für das Google Workspace-Konto Ihres Unternehmens deklarieren.

Wenn Sie die Standardwerte anderer von Google bereitgestellter Parameter nicht überschreiben möchten, müssen Sie diese nicht in Ihrer Konfigurationsdatei angeben. Weitere Informationen zu den von Google bereitgestellten Konfigurationsparametern, z. B. wie Sie bestimmte IDs und Schlüssel generieren, finden Sie unter Von Google bereitgestellte Konfigurationsparameter.

Sie können auch eigene Repository-spezifische Parameter zur Verwendung in Ihrer Konfigurationsdatei definieren.

Konfigurationsdatei an den Connector übergeben

Legen Sie das Systemattribut config so fest, dass die Konfigurationsdatei an den Connector übergeben wird. Sie können das Attribut beim Starten des Connectors mit dem Argument -D festlegen. Mit dem folgenden Befehl wird der Connector beispielsweise mit der Konfigurationsdatei MyConfig.properties gestartet:

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

Wenn dieses Argument fehlt, versucht das SDK, auf eine Standardkonfigurationsdatei mit dem Namen connector-config.properties zuzugreifen.

Durchquerungsstrategie festlegen

Die Hauptfunktion eines Inhaltsconnectors besteht darin, ein Repository zu durchsuchen und seine Daten zu indexieren. Sie müssen eine Durchlaufstrategie basierend auf der Größe und dem Layout der Daten in Ihrem Repository implementieren. Sie können Ihre eigene Strategie entwerfen oder eine der folgenden im SDK implementierten Strategien auswählen:

Durchlauf mit vollständiger Indexierung (Full Traversal)

Bei dieser Strategie wird das gesamte Repository gescannt und blind indexiert. Diese Strategie wird häufig verwendet, wenn Sie ein kleines Repository haben und es sich den Aufwand leisten kann, bei jeder Indexierung einen vollständigen Durchlauf vorzunehmen.

Diese Durchlaufstrategie eignet sich für kleine Repositories mit hauptsächlich statischen, nicht hierarchischen Daten. Sie können diese Durchlaufstrategie auch verwenden, wenn die Änderungserkennung schwierig ist oder vom Repository nicht unterstützt wird.

Durchlauf mit Teilindexierung (List Traversal)

Bei dieser Strategie wird das gesamte Repository einschließlich aller untergeordneten Knoten gescannt, um den Status der einzelnen Elemente zu ermitteln. Anschließend führt der Connector einen zweiten Durchlauf aus und indexiert nur Elemente, die neu sind oder seit der letzten Indexierung aktualisiert wurden. Diese Strategie wird in der Regel verwendet, um inkrementelle Aktualisierungen an einem vorhandenen Index durchzuführen, anstatt bei jeder Aktualisierung des Index einen vollständigen Durchlauf durchführen zu müssen.

Diese Durchlaufstrategie eignet sich, wenn die Änderungserkennung schwierig ist oder vom Repository nicht unterstützt wird, Sie nicht hierarchische Daten haben und mit sehr großen Datasets arbeiten.

Graph Traversal

Bei dieser Strategie wird der gesamte übergeordnete Knoten gescannt, um den Status der einzelnen Elemente zu ermitteln. Anschließend führt der Connector einen zweiten Durchlauf aus und indexiert nur Elemente im Stammknoten, die neu sind oder seit der letzten Indexierung aktualisiert wurden. Schließlich übergibt der Connector alle untergeordneten IDs und indexiert die Elemente in den untergeordneten Knoten, die neu sind oder aktualisiert wurden. Der Connector durchläuft rekursiv alle untergeordneten Knoten, bis alle Elemente bearbeitet sind. Ein solcher Durchlauf wird in der Regel für hierarchische Repositories verwendet, bei denen das Auflisten aller IDs nicht praktikabel ist.

Diese Strategie ist geeignet, wenn Sie hierarchische Daten haben, die gecrawlt werden müssen, z. B. eine Reihe von Verzeichnissen oder Webseiten.

Jede dieser Durchlaufstrategien wird durch eine Vorlagen-Connector-Klasse im SDK implementiert. Sie können zwar Ihre eigene Durchlaufstrategie implementieren, diese Vorlagen beschleunigen jedoch die Entwicklung Ihres Connectors erheblich. Wenn Sie einen Connector mithilfe einer Vorlage erstellen möchten, fahren Sie mit dem Abschnitt fort, der Ihrer Durchlaufstrategie entspricht:

Mithilfe einer Vorlagenklasse einen Full Traversal-Connector erstellen

Dieser Abschnitt bezieht sich auf Code-Snippets aus dem Beispiel FullTraversalSample.

Einstiegspunkt des Connectors implementieren

Der Einstiegspunkt für einen Connector ist die Methode main(). Die Hauptaufgabe dieser Methode besteht darin, eine Instanz der Klasse Application zu erstellen und deren Methode start() aufzurufen, um den Connector auszuführen.

Verwenden Sie vor dem Aufrufen von application.start() die Klasse IndexingApplication.Builder, um die Vorlage FullTraversalConnector zu instanziieren. FullTraversalConnector akzeptiert ein Repository-Objekt, dessen Methoden Sie implementieren. Das folgende Code-Snippet zeigt, wie die Methode main() implementiert wird:

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();
}

Nachdem Application.build von der Methode main() des Connectors aufgerufen wurde, ruft das SDK im Hintergrund die Methode initConfig() auf. Mit der Methode initConfig() werden die folgenden Aufgaben ausgeführt:

  1. Durch Aufrufen der Methode Configuation.isInitialized() wird dafür gesorgt, dass Configuration noch nicht initialisiert wurde.
  2. Ein Configuration-Objekt wird mit den von Google bereitgestellten Schlüssel/Wert-Paaren initialisiert. Jedes Schlüssel/Wert-Paar wird in einem ConfigValue-Objekt innerhalb des Configuration-Objekts gespeichert.

Repository-Schnittstelle implementieren

Die einzige Aufgabe des Repository-Objekts besteht darin, Repository-Elemente zu durchsuchen und zu indexieren. Wenn Sie eine Vorlage verwenden, müssen Sie nur bestimmte Methoden innerhalb der Repository-Schnittstelle überschreiben, um einen Inhaltsconnector zu erstellen. Welche Methoden Sie überschreiben, hängt von der verwendeten Vorlage und der Durchlaufstrategie ab. Überschreiben Sie für FullTraversalConnector die folgenden Methoden:

  • Die Methode init(). Wenn Sie ein Daten-Repository einrichten und initialisieren möchten, überschreiben Sie die Methode init().

  • Die Methode getAllDocs(). Wenn alle Elemente im Daten-Repository durchsucht und indexiert werden sollen, überschreiben Sie die Methode getAllDocs(). Diese Methode wird bei jedem geplanten Durchlauf einmal aufgerufen (wie in Ihrer Konfiguration definiert).

  • Optional: Die Methode getChanges(). Wenn Ihr Repository die Änderungserkennung unterstützt, überschreiben Sie die Methode getChanges(). Diese Methode wird bei jedem geplanten inkrementellen Durchlauf (wie in Ihrer Konfiguration definiert) einmal aufgerufen, um geänderte Elemente abzurufen und zu indexieren.

  • Optional: Die Methode close(). Wenn Sie eine Repository-Bereinigung ausführen müssen, überschreiben Sie die Methode close(). Diese Methode wird beim Herunterfahren des Connectors einmal aufgerufen.

Für jede der Methoden des Repository-Objekts wird ein Objekt des Typs ApiOperation zurückgegeben. Ein ApiOperation-Objekt führt eine Aktion in Form eines einzelnen oder möglicherweise mehrerer IndexingService.indexItem()-Aufrufe aus, um die tatsächliche Indexierung Ihres Repositorys zu veranlassen.

Benutzerdefinierte Konfigurationsparameter abrufen

Im Rahmen der Konfiguration des Connectors müssen Sie alle benutzerdefinierten Parameter aus dem Configuration-Objekt abrufen. Diese Aufgabe wird normalerweise in der Methode init() einer Repository-Klasse ausgeführt.

Die Klasse Configuration bietet mehrere Methoden, unterschiedliche Datentypen aus einer Konfiguration abzurufen. Bei jeder Methode wird ein ConfigValue-Objekt zurückgegeben. Anschließend verwenden Sie die Methode get() des ConfigValue-Objekts, um den tatsächlichen Wert abzurufen. Das folgende Snippet aus FullTraversalSample zeigt, wie eine einzelne benutzerdefinierte Ganzzahl aus einem Configuration-Objekt abgerufen wird:

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

Verwenden Sie zum Abrufen und Parsen eines Parameters, der mehrere Werte enthält, einen der Typparser der Configuration-Klasse, um die Daten in einzelne Blöcke zu parsen. Das folgende Snippet aus dem Connectorbeispiel des Tutorials zeigt, wie Sie mithilfe der Methode getMultiValue eine Liste mit Namen von GitHub-Repositories erhalten:

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

Durchlauf mit vollständiger Indexierung (Full Traversal) durchführen

Überschreiben Sie getAllDocs(), um einen vollständigen Durchlauf (Full Traversal) durchzuführen und das Repository zu indexieren. Die Methode getAllDocs() akzeptiert einen Prüfpunkt. Dieser dient dazu, die Indexierung bei einem bestimmten Element fortzusetzen, sollte der Prozess unterbrochen werden. Führen Sie für jedes Element in Ihrem Repository die folgenden Schritte in der Methode getAllDocs() aus:

  1. Legen Sie die Berechtigungen fest.
  2. Legen Sie die Metadaten für das zu indexierende Element fest.
  3. Kombinieren Sie die Metadaten und das Element in einer indexierbaren RepositoryDoc.
  4. Verpacken Sie jedes indexierbare Element einem Iteration, die von der Methode getAllDocs() zurückgegeben wird. getAllDocs() gibt tatsächlich ein CheckpointCloseableIterable zurück. Dabei handelt es sich um eine Iteration von ApiOperation-Objekten, wobei jedes Objekt eine API-Anfrage darstellt, die für RepositoryDoc ausgeführt wird, z. B. für die Indexierung.

Wenn die Gruppe von Elementen zu groß für die Verarbeitung in einem einzigen Aufruf ist, fügen Sie einen Checkpoint ein und legen Sie hasMore(true) fest, um anzugeben, dass weitere Elemente für die Indexierung verfügbar sind.

Berechtigungen für ein Element festlegen

In Ihrem Repository wird eine Access Control List (ACL) verwendet, um die Nutzer oder Gruppen zu identifizieren, die Zugriff auf ein Element haben. Eine ACL ist eine Liste der IDs für Gruppen oder Nutzer, die auf das Element zugreifen können.

Sie müssen die von Ihrem Repository verwendete ACL duplizieren, damit nur Nutzer mit Zugriff auf ein Element es in einem Suchergebnis sehen können. Die ACL für ein Element muss beim Indexieren angegeben werden, damit Google Cloud Search über die Informationen verfügt, die zum Bereitstellen der korrekten Zugriffsebene für das Element erforderlich sind.

Das Content Connector SDK bietet eine Vielzahl von ACL-Klassen und -Methoden, um die ACLs der meisten Repositories zu modellieren. Sie müssen die ACL für jedes Element in Ihrem Repository analysieren und eine entsprechende ACL für Google Cloud Search erstellen, wenn Sie ein Element indexieren. Wenn in der ACL Ihres Repositorys Konzepte wie die ACL-Vererbung zum Einsatz kommen, kann es schwierig sein, diese ACL zu modellieren. Weitere Informationen

Hinweis:Die Cloud Search Indexing API unterstützt ACLs für einzelne Domains. Domainübergreifende ACLs werden nicht unterstützt. Verwenden Sie die Klasse Acl.Builder, um den Zugriff auf die einzelnen Elemente mithilfe einer ACL festzulegen. Mit dem folgenden Code-Snippet aus dem vollständigen Durchlaufbeispiel können alle Nutzer oder „Hauptkonten“ (getCustomerPrincipal()) beim Ausführen einer Suche alle Elemente (.setReaders()) lesen.

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

Sie müssen mit ACLs vertraut sein, um ACLs für das Repository richtig modellieren zu können. Sie können beispielsweise Dateien in einem Dateisystem indexieren, das ein Übernahmemodell verwendet, bei dem untergeordnete Ordner Berechtigungen von übergeordneten Ordnern erben. Für die Modellierung der ACL-Vererbung sind zusätzliche Informationen erforderlich. Weitere Informationen hierzu finden Sie im Artikel ACLs zuordnen.

Metadaten für ein Element festlegen

Metadaten werden in einem Item-Objekt gespeichert. Zum Erstellen eines Item benötigen Sie mindestens die folgenden Angaben: die eindeutige String-ID, den Elementtyp, die ACL, die URL und die Elementversion. Das folgende Code-Snippet zeigt, wie ein Item mit der Helper-Klasse IndexingItemBuilder erstellt wird.

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();

Indexierbares Element erstellen

Nachdem Sie die Metadaten für das Element festgelegt haben, können Sie das tatsächliche indexierbare Element mithilfe der Klasse RepositoryDoc.Builder erstellen. Das folgende Beispiel zeigt, wie ein einzelnes indexierbares Element erstellt wird.

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();

Ein RepositoryDoc ist ein ApiOperation-Typ, der die eigentliche IndexingService.indexItem()-Anfrage ausführt.

Sie können auch die Methode setRequestMode() der Klasse RepositoryDoc.Builder verwenden, um die Indexierungsanfrage als ASYNCHRONOUS oder SYNCHRONOUS zu identifizieren:

ASYNCHRONOUS
Im asynchronen Modus ist die Latenz zwischen Indexierung und Ausgabe höher, sodass ein hohes Durchsatzkontingent für Indexierungsanfragen möglich ist. Der asynchrone Modus wird für die anfängliche Indexierung (Backfill) des gesamten Repositorys empfohlen.
SYNCHRONOUS
Im synchronen Modus ist die Latenz zwischen Indexierung und Bereitstellung geringer und das Durchsatzkontingent ist begrenzt. Für die Indexierung von Updates und Änderungen am Repository wird der synchrone Modus empfohlen. Wenn keine Angabe erfolgt, wird standardmäßig der Anfragemodus SYNCHRONOUS verwendet.

Jedes indexierbare Element in einen Iterator verpacken

Die Methode getAllDocs() gibt ein Iterator zurück, genauer gesagt ein CheckpointCloseableIterable von RepositoryDoc-Objekten. Mit der Klasse CheckpointClosableIterableImpl.Builder können Sie einen Iterator erstellen und zurückgeben. Das folgende Code-Snippet zeigt, wie ein Iteration erstellt und zurückgegeben wird.

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

Das SDK führt jeden Indexierungsaufruf aus, der im Iterator enthalten ist.

Nächste Schritte

Als Nächstes könnten Sie Folgendes tun:

List Traversal-Connector mithilfe einer Vorlagenklasse erstellen

Die Cloud Search-Indexierungswarteschlange enthält IDs und optionale Hashwerte für jedes Element im Repository. Mit einem List Traversal-Connector werden Element-IDs der Indexierungswarteschlange in Google Cloud Search hinzugefügt und nacheinander für die Indexierung abgerufen. In Google Cloud Search werden Warteschlangen verwaltet und Inhalte verglichen, um den Status der Elemente zu ermitteln, z. B. ob ein Element aus dem Repository gelöscht wurde. Weitere Informationen zur Cloud Search-Indexierungswarteschlange

Dieser Abschnitt bezieht sich auf Code-Snippets aus dem Beispiel ListTraversalSample.

Einstiegspunkt des Connectors implementieren

Der Einstiegspunkt für einen Connector ist die Methode main(). Die Hauptaufgabe dieser Methode besteht darin, eine Instanz der Klasse Application zu erstellen und deren Methode start() aufzurufen, um den Connector auszuführen.

Verwenden Sie vor dem Aufrufen von application.start() die Klasse IndexingApplication.Builder, um die Vorlage ListingConnector zu instanziieren. Für ListingConnector wird ein Repository-Objekt akzeptiert, dessen Methoden Sie implementieren. Das folgende Snippet zeigt, wie das ListingConnector und das zugehörige Repository instanziiert werden:

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();
}

Nachdem Application.build von der Methode main() des Connectors aufgerufen wurde, ruft das SDK im Hintergrund die Methode initConfig() auf. Die Methode initConfig():

  1. Durch Aufrufen der Methode Configuation.isInitialized() wird dafür gesorgt, dass Configuration noch nicht initialisiert wurde.
  2. Ein Configuration-Objekt wird mit den von Google bereitgestellten Schlüssel/Wert-Paaren initialisiert. Jedes Schlüssel/Wert-Paar wird in einem ConfigValue-Objekt innerhalb des Configuration-Objekts gespeichert.

Repository-Schnittstelle implementieren

Die einzige Aufgabe des Repository-Objekts besteht darin, Repository-Elemente zu durchsuchen und zu indexieren. Wenn Sie eine Vorlage verwenden, müssen Sie nur bestimmte Methoden in der Repository-Schnittstelle überschreiben, um einen Inhaltsconnector zu erstellen. Welche das sind, hängt von der verwendeten Vorlage und der Durchlaufstrategie ab. Überschreiben Sie für ListingConnector die folgenden Methoden:

  • Die Methode init(). Wenn Sie ein Daten-Repository einrichten und initialisieren möchten, überschreiben Sie die Methode init().

  • Die Methode getIds(). Wenn Sie IDs und Hashwerte für alle Datensätze im Repository abrufen möchten, überschreiben Sie die Methode getIds().

  • Die Methode getDoc(). Wenn Sie im Index Elemente hinzufügen, bearbeiten oder löschen möchten, überschreiben Sie die Methode getDoc().

  • Optional: Die Methode getChanges(). Wenn Ihr Repository die Änderungserkennung unterstützt, überschreiben Sie die Methode getChanges(). Diese Methode wird bei jedem geplanten inkrementellen Durchlauf (wie in Ihrer Konfiguration definiert) einmal aufgerufen, um geänderte Elemente abzurufen und zu indexieren.

  • Optional: Die Methode close(). Wenn Sie eine Repository-Bereinigung ausführen müssen, überschreiben Sie die Methode close(). Diese Methode wird beim Herunterfahren des Connectors einmal aufgerufen.

Für jede der Methoden des Repository-Objekts wird ein Objekt des Typs ApiOperation zurückgegeben. Ein ApiOperation-Objekt führt eine Aktion in Form eines einzelnen oder möglicherweise mehrerer IndexingService.indexItem()-Aufrufe aus, um die tatsächliche Indexierung Ihres Repositorys zu veranlassen.

Benutzerdefinierte Konfigurationsparameter abrufen

Im Rahmen der Konfiguration des Connectors müssen Sie alle benutzerdefinierten Parameter aus dem Configuration-Objekt abrufen. Diese Aufgabe wird normalerweise in der Methode init() einer Repository-Klasse ausgeführt.

Die Klasse Configuration bietet mehrere Methoden, unterschiedliche Datentypen aus einer Konfiguration abzurufen. Bei jeder Methode wird ein ConfigValue-Objekt zurückgegeben. Anschließend verwenden Sie die Methode get() des ConfigValue-Objekts, um den tatsächlichen Wert abzurufen. Das folgende Snippet aus FullTraversalSample zeigt, wie eine einzelne benutzerdefinierte Ganzzahl aus einem Configuration-Objekt abgerufen wird:

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

Verwenden Sie zum Abrufen und Parsen eines Parameters, der mehrere Werte enthält, einen der Typparser der Configuration-Klasse, um die Daten in einzelne Blöcke zu parsen. Das folgende Snippet aus dem Connectorbeispiel des Tutorials zeigt, wie Sie mithilfe der Methode getMultiValue eine Liste mit Namen von GitHub-Repositories erhalten:

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

List Traversal durchführen

Überschreiben Sie die Methode getIds(), um IDs und Hashwerte für alle Datensätze im Repository abzurufen. Für die Methode getIds() kann ein Prüfpunkt verwendet werden. Dieser dient dazu, die Indexierung bei einem bestimmten Element fortzusetzen, sollte der Prozess unterbrochen werden.

Überschreiben Sie als Nächstes die Methode getDoc(), um jedes Element in der Cloud Search-Indexierungswarteschlange zu verarbeiten.

Element-IDs und Hashwerte senden

Überschreiben Sie getIds(), um die Element-IDs und die zugehörigen Inhalts-Hashwerte aus dem Repository abzurufen. ID- und Hashwert-Paare werden dann in eine Push-Vorgangsanfrage an die Cloud Search-Indexierungswarteschlange gepackt. Stamm- oder übergeordnete IDs werden normalerweise zuerst übertragen, gefolgt von untergeordneten IDs, bis die gesamte Hierarchie der Elemente verarbeitet wurde.

Die Methode getIds() akzeptiert einen Prüfpunkt, der das letzte zu indexierende Element darstellt. Dieser ermöglicht es, die Indexierung bei einem bestimmten Element fortzusetzen, sollte der Prozess unterbrochen werden. Führen Sie für jedes Element in Ihrem Repository die folgenden Schritte in der Methode getIds() aus:

  • Rufen Sie jede Element-ID und den zugehörigen Hashwert aus dem Repository ab.
  • Verpacken Sie jedes ID-Hash-Wert-Paar in eine PushItems.
  • Kombinieren Sie alle PushItems in einem Iterator, der von der Methode getIds() zurückgegeben wird. getIds() gibt tatsächlich ein CheckpointCloseableIterable zurück. Dabei handelt es sich um eine Iteration von ApiOperation-Objekten, wobei jedes Objekt eine API-Anfrage darstellt, die für ein RepositoryDoc-Objekt ausgeführt wird, z. B. durch das Übertragen der Elemente in die Warteschlange.

Das folgende Code-Snippet zeigt, wie Sie die einzelnen Element-IDs und Hash-Werte abrufen und in eine PushItems einfügen. PushItems ist eine ApiOperation-Anfrage, mit der ein Element in die Cloud Search-Indexierungswarteschlange aufgenommen wird.

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);
}

Das folgende Code-Snippet zeigt, wie Sie mit der Klasse PushItems.Builder die IDs und Hashwerte in einer einzigen Push-ApiOperation verpacken.

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

Die Elemente werden zur weiteren Verarbeitung der Cloud Search-Indexierungswarteschlange hinzugefügt.

Alle Artikel abrufen und verarbeiten

Überschreiben Sie getDoc(), um jedes Element in der Cloud Search-Indexierungswarteschlange zu verarbeiten. Ein Element kann neu, geändert, unverändert oder nicht mehr im Quell-Repository vorhanden sein. Rufen Sie jedes neue oder geänderte Element ab und indexieren Sie es. Entfernen Sie Elemente aus dem Index, die nicht mehr im Quell-Repository vorhanden sind.

Die Methode getDoc() akzeptiert ein Element aus der Google Cloud Search-Indexierungswarteschlange. Führen Sie für jedes Element in der Warteschlange die folgenden Schritte in der Methode getDoc() aus:

  1. Prüfen Sie, ob die ID des Elements aus der Cloud Search-Indexierungswarteschlange im Repository vorhanden ist. Wenn nicht, löschen Sie das Element aus dem Index.

  2. Fragen Sie den Index nach dem Status des Elements ab. Wenn ein Element unverändert ist (ACCEPTED), tun Sie nichts.

  3. Geänderte oder neue Elemente indexieren:

    1. Legen Sie die Berechtigungen fest.
    2. Legen Sie die Metadaten für das zu indexierende Element fest.
    3. Kombinieren Sie die Metadaten und das Element in einer indexierbaren RepositoryDoc.
    4. Geben Sie RepositoryDoc zurück.

Hinweis: Die Vorlage ListingConnector unterstützt nicht die Rückgabe von null für die Methode getDoc(). Die Rückgabe von null führt zu einem NullPointerException.

Umgang mit gelöschten Elementen

Das folgende Code-Snippet zeigt, wie Sie feststellen können, ob ein Element im Repository vorhanden ist, und es gegebenenfalls löschen.

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 ist eine Datenstruktur, die das Repository darstellt. Wenn documentID nicht in documents gefunden wird, geben Sie APIOperations.deleteItem(resourceName) zurück, um das Element aus dem Index zu löschen.

Umgang mit unveränderten Elementen

Das folgende Code-Snippet zeigt, wie Sie den Status von Elementen in der Cloud Search-Indexierungswarteschlange abfragen und mit unveränderten Elementen umgehen.

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();
}

Um festzustellen, ob das Element unverändert ist, prüfen Sie den Status des Elements sowie andere Metadaten, die auf eine Änderung hinweisen können. In diesem Beispiel wird anhand des Metadaten-Hash ermittelt, ob das Element geändert wurde.

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);
}

Berechtigungen für ein Element festlegen

In Ihrem Repository wird eine Access Control List (ACL) verwendet, um die Nutzer oder Gruppen zu identifizieren, die Zugriff auf ein Element haben. Eine ACL ist eine Liste der IDs für Gruppen oder Nutzer, die auf das Element zugreifen können.

Sie müssen die von Ihrem Repository verwendete ACL duplizieren, damit nur Nutzer mit Zugriff auf ein Element es in einem Suchergebnis sehen können. Die ACL für ein Element muss beim Indexieren angegeben werden, damit Google Cloud Search über die Informationen verfügt, die zum Bereitstellen der korrekten Zugriffsebene für das Element erforderlich sind.

Das Content Connector SDK bietet eine Vielzahl von ACL-Klassen und -Methoden, um die ACLs der meisten Repositories zu modellieren. Sie müssen die ACL für jedes Element in Ihrem Repository analysieren und eine entsprechende ACL für Google Cloud Search erstellen, wenn Sie ein Element indexieren. Wenn in der ACL Ihres Repositorys Konzepte wie die ACL-Vererbung zum Einsatz kommen, kann es schwierig sein, diese ACL zu modellieren. Weitere Informationen

Hinweis:Die Cloud Search Indexing API unterstützt ACLs für einzelne Domains. Domainübergreifende ACLs werden nicht unterstützt. Verwenden Sie die Klasse Acl.Builder, um den Zugriff auf die einzelnen Elemente mithilfe einer ACL festzulegen. Mit dem folgenden Code-Snippet aus dem vollständigen Durchlaufbeispiel können alle Nutzer oder „Hauptkonten“ (getCustomerPrincipal()) beim Ausführen einer Suche alle Elemente (.setReaders()) lesen.

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

Sie müssen mit ACLs vertraut sein, um ACLs für das Repository richtig modellieren zu können. Sie können beispielsweise Dateien in einem Dateisystem indexieren, das ein Übernahmemodell verwendet, bei dem untergeordnete Ordner Berechtigungen von übergeordneten Ordnern erben. Für die Modellierung der ACL-Vererbung sind zusätzliche Informationen erforderlich. Weitere Informationen hierzu finden Sie im Artikel ACLs zuordnen.

Metadaten für ein Element festlegen

Metadaten werden in einem Item-Objekt gespeichert. Zum Erstellen eines Item benötigen Sie mindestens die folgenden Angaben: die eindeutige String-ID, den Elementtyp, die ACL, die URL und die Elementversion. Das folgende Code-Snippet zeigt, wie ein Item mit der Helper-Klasse IndexingItemBuilder erstellt wird.

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();

Indexierbares Element erstellen

Nachdem Sie die Metadaten für das Element festgelegt haben, können Sie mit dem RepositoryDoc.Builder das tatsächliche indexierbare Element erstellen. Das folgende Beispiel zeigt, wie ein einzelnes indexierbares Element erstellt wird.

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();

Ein RepositoryDoc ist ein ApiOperation-Typ, der die eigentliche IndexingService.indexItem()-Anfrage ausführt.

Sie können auch die Methode setRequestMode() der Klasse RepositoryDoc.Builder verwenden, um die Indexierungsanfrage als ASYNCHRONOUS oder SYNCHRONOUS zu identifizieren:

ASYNCHRONOUS
Im asynchronen Modus ist die Latenz zwischen Indexierung und Ausgabe höher, sodass ein hohes Durchsatzkontingent für Indexierungsanfragen möglich ist. Der asynchrone Modus wird für die anfängliche Indexierung (Backfill) des gesamten Repositorys empfohlen.
SYNCHRONOUS
Im synchronen Modus ist die Latenz zwischen Indexierung und Bereitstellung geringer und das Durchsatzkontingent ist begrenzt. Für die Indexierung von Updates und Änderungen am Repository wird der synchrone Modus empfohlen. Wenn keine Angabe erfolgt, wird standardmäßig der Anfragemodus SYNCHRONOUS verwendet.

Nächste Schritte

Als Nächstes könnten Sie Folgendes tun:

Graph Traversal-Connector mithilfe einer Vorlagenklasse erstellen

Die Cloud Search-Indexierungswarteschlange enthält IDs und optionale Hashwerte für jedes Element im Repository. Mit einem Graph Traversal-Connector werden die Element-IDs der Indexierungswarteschlange von Google Cloud Search hinzugefügt und nacheinander für die Indexierung abgerufen. Google Cloud Search verwaltet Warteschlangen und vergleicht Inhalte von Warteschlangen, um den Status eines Elements zu ermitteln, beispielsweise, ob ein Element aus dem Repository gelöscht wurde. Weitere Informationen zur Cloud Search-Indexierungswarteschlange

Während der Indexierung wird der Elementinhalt aus dem Daten-Repository abgerufen und alle untergeordneten Element-IDs werden in die Warteschlange verschoben. Der Connector verarbeitet die über- und untergeordneten IDs rekursiv, bis alle Elemente verarbeitet sind.

Dieser Abschnitt bezieht sich auf Code-Snippets aus dem Beispiel GraphTraversalSample.

Einstiegspunkt des Connectors implementieren

Der Einstiegspunkt für einen Connector ist die Methode main(). Die Hauptaufgabe dieser Methode besteht darin, eine Instanz der Klasse Application zu erstellen und deren Methode start() aufzurufen, um den Connector auszuführen.

Verwenden Sie vor dem Aufrufen von application.start() die Klasse IndexingApplication.Builder, um die Vorlage ListingConnector zu instanziieren. ListingConnector akzeptiert ein Repository-Objekt, dessen Methoden Sie implementieren.

Das folgende Snippet zeigt, wie das ListingConnector und das zugehörige Repository instanziiert werden:

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();
}

Nachdem Application.build von der Methode main() des Connectors aufgerufen wurde, ruft das SDK im Hintergrund die Methode initConfig() auf. Die Methode initConfig():

  1. Durch Aufrufen der Methode Configuation.isInitialized() wird dafür gesorgt, dass Configuration noch nicht initialisiert wurde.
  2. Ein Configuration-Objekt wird mit den von Google bereitgestellten Schlüssel/Wert-Paaren initialisiert. Jedes Schlüssel/Wert-Paar wird in einem ConfigValue-Objekt innerhalb des Configuration-Objekts gespeichert.

Repository-Schnittstelle implementieren

Die einzige Aufgabe des Repository-Objekts besteht darin, Repository-Elemente zu durchsuchen und zu indexieren. Wenn Sie eine Vorlage verwenden, müssen Sie nur bestimmte Methoden in der Repository-Schnittstelle überschreiben, um einen Inhaltsconnector zu erstellen. Welche das sind, hängt von der verwendeten Vorlage und der Durchlaufstrategie ab. Für ListingConnector überschreiben Sie die folgenden Methoden:

  • Die Methode init(). Wenn Sie ein Daten-Repository einrichten und initialisieren möchten, überschreiben Sie die Methode init().

  • Die Methode getIds(). Wenn Sie IDs und Hashwerte für alle Datensätze im Repository abrufen möchten, überschreiben Sie die Methode getIds().

  • Die Methode getDoc(). Wenn Sie im Index Elemente hinzufügen, bearbeiten oder löschen möchten, überschreiben Sie die Methode getDoc().

  • Optional: Die Methode getChanges(). Wenn Ihr Repository die Änderungserkennung unterstützt, überschreiben Sie die Methode getChanges(). Diese Methode wird bei jedem geplanten inkrementellen Durchlauf (wie in Ihrer Konfiguration definiert) einmal aufgerufen, um geänderte Elemente abzurufen und zu indexieren.

  • Optional: Die Methode close(). Wenn Sie eine Repository-Bereinigung ausführen müssen, überschreiben Sie die Methode close(). Diese Methode wird beim Herunterfahren des Connectors einmal aufgerufen.

Für jede der Methoden des Repository-Objekts wird ein Typ von ApiOperation-Objekt zurückgegeben. Ein ApiOperation-Objekt führt eine Aktion in Form eines einzelnen oder möglicherweise mehrerer Aufrufe des Typs IndexingService.indexItem() aus, um die tatsächliche Indexierung Ihres Repositorys zu veranlassen.

Benutzerdefinierte Konfigurationsparameter abrufen

Im Rahmen der Konfiguration des Connectors müssen Sie alle benutzerdefinierten Parameter aus dem Configuration-Objekt abrufen. Diese Aufgabe wird normalerweise in der Methode init() einer Repository-Klasse ausgeführt.

Die Klasse Configuration bietet mehrere Methoden, unterschiedliche Datentypen aus einer Konfiguration abzurufen. Bei jeder Methode wird ein ConfigValue-Objekt zurückgegeben. Anschließend verwenden Sie die Methode get() des ConfigValue-Objekts, um den tatsächlichen Wert abzurufen. Das folgende Snippet aus FullTraversalSample zeigt, wie eine einzelne benutzerdefinierte Ganzzahl aus einem Configuration-Objekt abgerufen wird:

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

Verwenden Sie zum Abrufen und Parsen eines Parameters, der mehrere Werte enthält, einen der Typparser der Configuration-Klasse, um die Daten in einzelne Blöcke zu parsen. Das folgende Snippet aus dem Connectorbeispiel des Tutorials zeigt, wie Sie mithilfe der Methode getMultiValue eine Liste mit Namen von GitHub-Repositories erhalten:

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

Graph Traversal durchführen

Überschreiben Sie die Methode getIds(), um IDs und Hashwerte für alle Datensätze im Repository abzurufen. Für die Methode getIds() kann ein Prüfpunkt verwendet werden. Dieser dient dazu, die Indexierung bei einem bestimmten Element fortzusetzen, sollte der Prozess unterbrochen werden.

Überschreiben Sie als Nächstes die Methode getDoc(), um jedes Element in der Cloud Search-Indexierungswarteschlange zu verarbeiten.

Element-IDs und Hashwerte senden

Überschreiben Sie getIds(), um die Element-IDs und die zugehörigen Inhalts-Hashwerte aus dem Repository abzurufen. ID- und Hashwert-Paare werden dann in eine Push-Vorgangsanfrage an die Cloud Search-Indexierungswarteschlange gepackt. Stamm- oder übergeordnete IDs werden normalerweise zuerst übertragen, gefolgt von untergeordneten IDs, bis die gesamte Hierarchie der Elemente verarbeitet wurde.

Die Methode getIds() akzeptiert einen Prüfpunkt, der das letzte zu indexierende Element darstellt. Dieser ermöglicht es, die Indexierung bei einem bestimmten Element fortzusetzen, sollte der Prozess unterbrochen werden. Führen Sie für jedes Element in Ihrem Repository die folgenden Schritte in der Methode getIds() aus:

  • Rufen Sie jede Element-ID und den zugehörigen Hashwert aus dem Repository ab.
  • Verpacken Sie jedes ID-Hash-Wert-Paar in eine PushItems.
  • Kombinieren Sie jeden PushItems in einem Iteration, die von der Methode getIds() zurückgegeben wird. getIds() gibt tatsächlich ein CheckpointCloseableIterable zurück. Dabei handelt es sich um eine Iteration von ApiOperation-Objekten, wobei jedes Objekt eine API-Anfrage darstellt, die für ein RepositoryDoc-Objekt ausgeführt wird, z. B. durch das Übertragen der Elemente in die Warteschlange.

Das folgende Code-Snippet zeigt, wie die einzelnen Element-IDs und Hash-Werte abgerufen und in eine PushItems eingefügt werden. PushItems ist eine ApiOperation-Anfrage, mit der ein Element in die Cloud Search-Indexierungswarteschlange aufgenommen wird.

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

Das folgende Code-Snippet zeigt, wie Sie mit der Klasse PushItems.Builder die IDs und Hashwerte in einem einzigen Push-ApiOperation verpacken.

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

Die Elemente werden zur weiteren Verarbeitung der Cloud Search-Indexierungswarteschlange hinzugefügt.

Alle Artikel abrufen und verarbeiten

Überschreiben Sie getDoc(), um jedes Element in der Cloud Search-Indexierungswarteschlange zu verarbeiten. Ein Element kann neu, geändert, unverändert oder nicht mehr im Quell-Repository vorhanden sein. Rufen Sie jedes neue oder geänderte Element ab und indexieren Sie es. Entfernen Sie Elemente aus dem Index, die nicht mehr im Quell-Repository vorhanden sind.

Die Methode getDoc() akzeptiert ein Element aus der Cloud Search-Indexierungswarteschlange. Führen Sie für jedes Element in der Warteschlange die folgenden Schritte in der Methode getDoc() aus:

  1. Prüfen Sie, ob im Repository die ID des Elements aus der Cloud Search-Indexierungswarteschlange vorhanden ist. Wenn nicht, löschen Sie das Element aus dem Index. Wenn das Element vorhanden ist, fahren Sie mit dem nächsten Schritt fort.

  2. Geänderte oder neue Elemente indexieren:

    1. Legen Sie die Berechtigungen fest.
    2. Legen Sie die Metadaten für das zu indexierende Element fest.
    3. Kombinieren Sie die Metadaten und das Element in einer indexierbaren RepositoryDoc.
    4. Fügen Sie die untergeordneten IDs zur weiteren Verarbeitung der Cloud Search-Indexierungswarteschlange hinzu.
    5. Geben Sie RepositoryDoc zurück.

Umgang mit gelöschten Elementen

Das folgende Code-Snippet zeigt, wie Sie feststellen, ob ein Element im Index vorhanden ist, und es gegebenenfalls löschen.

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);

Berechtigungen für ein Element festlegen

In Ihrem Repository wird eine Access Control List (ACL) verwendet, um die Nutzer oder Gruppen zu identifizieren, die Zugriff auf ein Element haben. Eine ACL ist eine Liste der IDs für Gruppen oder Nutzer, die auf das Element zugreifen können.

Sie müssen die von Ihrem Repository verwendete ACL duplizieren, damit nur Nutzer mit Zugriff auf ein Element es in einem Suchergebnis sehen können. Die ACL für ein Element muss beim Indexieren angegeben werden, damit Google Cloud Search über die Informationen verfügt, die zum Bereitstellen der korrekten Zugriffsebene für das Element erforderlich sind.

Das Content Connector SDK bietet eine Vielzahl von ACL-Klassen und -Methoden, um die ACLs der meisten Repositories zu modellieren. Sie müssen die ACL für jedes Element in Ihrem Repository analysieren und eine entsprechende ACL für Google Cloud Search erstellen, wenn Sie ein Element indexieren. Wenn in der ACL Ihres Repositorys Konzepte wie die ACL-Vererbung zum Einsatz kommen, kann es schwierig sein, diese ACL zu modellieren. Weitere Informationen

Hinweis:Die Cloud Search Indexing API unterstützt ACLs für einzelne Domains. Domainübergreifende ACLs werden nicht unterstützt. Verwenden Sie die Klasse Acl.Builder, um den Zugriff auf die einzelnen Elemente mithilfe einer ACL festzulegen. Mit dem folgenden Code-Snippet aus dem vollständigen Durchlaufbeispiel können alle Nutzer oder „Hauptkonten“ (getCustomerPrincipal()) beim Ausführen einer Suche alle Elemente (.setReaders()) lesen.

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

Sie müssen mit ACLs vertraut sein, um ACLs für das Repository richtig modellieren zu können. Sie können beispielsweise Dateien in einem Dateisystem indexieren, das ein Übernahmemodell verwendet, bei dem untergeordnete Ordner Berechtigungen von übergeordneten Ordnern erben. Für die Modellierung der ACL-Vererbung sind zusätzliche Informationen erforderlich. Weitere Informationen hierzu finden Sie im Artikel ACLs zuordnen.

Metadaten für ein Element festlegen

Metadaten werden in einem Item-Objekt gespeichert. Zum Erstellen eines Item benötigen Sie mindestens die folgenden Angaben: die eindeutige String-ID, den Elementtyp, die ACL, die URL und die Elementversion. Das folgende Code-Snippet zeigt, wie ein Item mit der Helper-Klasse IndexingItemBuilder erstellt wird.

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();

Indexierbares Element erstellen

Nachdem Sie die Metadaten für das Element festgelegt haben, können Sie mit dem RepositoryDoc.Builder das tatsächliche indexierbare Element erstellen. Das folgende Beispiel zeigt, wie ein einzelnes indexierbares Element erstellt wird.

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);

Ein RepositoryDoc ist ein ApiOperation-Typ, der die eigentliche IndexingService.indexItem()-Anfrage ausführt.

Sie können auch die Methode setRequestMode() der Klasse RepositoryDoc.Builder verwenden, um die Indexierungsanfrage als ASYNCHRONOUS oder SYNCHRONOUS zu identifizieren:

ASYNCHRONOUS
Im asynchronen Modus ist die Latenz zwischen Indexierung und Ausgabe höher, sodass ein hohes Durchsatzkontingent für Indexierungsanfragen möglich ist. Der asynchrone Modus wird für die anfängliche Indexierung (Backfill) des gesamten Repositorys empfohlen.
SYNCHRONOUS
Im synchronen Modus ist die Latenz zwischen Indexierung und Bereitstellung geringer und das Durchsatzkontingent ist begrenzt. Für die Indexierung von Updates und Änderungen am Repository wird der synchrone Modus empfohlen. Wenn keine Angabe erfolgt, wird standardmäßig der Anfragemodus SYNCHRONOUS verwendet.

Untergeordnete IDs in die Cloud Search-Indexierungswarteschlange aufnehmen

Das folgende Code-Snippet zeigt, wie die untergeordneten IDs des derzeit verarbeiteten übergeordneten Elements in die Warteschlange für die Verarbeitung aufgenommen werden. Diese IDs werden verarbeitet, nachdem das übergeordnete Element indexiert wurde.

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();

Nächste Schritte

Als Nächstes könnten Sie Folgendes tun:

Inhaltsconnectors mit der REST API erstellen

In den folgenden Abschnitten wird erläutert, wie Sie mithilfe der REST API einen Inhaltsconnector erstellen.

Durchquerungsstrategie festlegen

Die Hauptfunktion eines Inhaltsconnectors besteht darin, ein Repository zu durchsuchen und seine Daten zu indexieren. Sie müssen eine Durchlaufstrategie basierend auf der Größe und dem Layout der Daten in Ihrem Repository implementieren. Es gibt drei gängige Durchlaufstrategien:

Durchlauf mit vollständiger Indexierung (Full Traversal)

Bei dieser Strategie wird das gesamte Repository gescannt und blind indexiert. Diese Strategie wird häufig verwendet, wenn Sie ein kleines Repository haben und es sich den Aufwand leisten kann, bei jeder Indexierung einen vollständigen Durchlauf vorzunehmen.

Diese Durchlaufstrategie eignet sich für kleine Repositories mit hauptsächlich statischen, nicht hierarchischen Daten. Sie können diese Durchlaufstrategie auch verwenden, wenn die Änderungserkennung schwierig ist oder vom Repository nicht unterstützt wird.

Durchlauf mit Teilindexierung (List Traversal)

Bei dieser Strategie wird das gesamte Repository einschließlich aller untergeordneten Knoten gescannt, um den Status der einzelnen Elemente zu ermitteln. Anschließend führt der Connector einen zweiten Durchlauf aus und indexiert nur Elemente, die neu sind oder seit der letzten Indexierung aktualisiert wurden. Diese Strategie wird in der Regel verwendet, um inkrementelle Aktualisierungen an einem vorhandenen Index durchzuführen, anstatt bei jeder Aktualisierung des Index einen vollständigen Durchlauf durchführen zu müssen.

Diese Durchlaufstrategie eignet sich, wenn die Änderungserkennung schwierig ist oder vom Repository nicht unterstützt wird, Sie nicht hierarchische Daten haben und mit sehr großen Datasets arbeiten.

Graph Traversal

Bei dieser Strategie wird der gesamte übergeordnete Knoten gescannt, um den Status der einzelnen Elemente zu ermitteln. Anschließend führt der Connector einen zweiten Durchlauf aus und indexiert nur Elemente im Stammknoten, die neu sind oder seit der letzten Indexierung aktualisiert wurden. Schließlich übergibt der Connector alle untergeordneten IDs und indexiert die Elemente in den untergeordneten Knoten, die neu sind oder aktualisiert wurden. Der Connector durchläuft rekursiv alle untergeordneten Knoten, bis alle Elemente bearbeitet sind. Ein solcher Durchlauf wird in der Regel für hierarchische Repositories verwendet, bei denen das Auflisten aller IDs nicht praktikabel ist.

Diese Strategie ist geeignet, wenn Sie hierarchische Daten haben, die gecrawlt werden müssen, z. B. Serienverzeichnisse oder Webseiten.

Durchquerungsstrategie und Indexelemente implementieren

Jedes indexierbare Element für Cloud Search wird in der Cloud Search API als Element bezeichnet. Ein Element kann eine Datei, ein Ordner, eine Zeile in einer CSV-Datei oder ein Datenbankeintrag sein.

Sobald Ihr Schema registriert ist, können Sie den Index so befüllen:

  1. Optional: Verwenden Sie items.upload, um Dateien, die größer als 100 KiB sind, für die Indexierung hochzuladen. Bei kleineren Dateien betten Sie den Inhalt mit items.index als inlineContent ein.

  2. Optional: Verwenden Sie media.upload, um Mediendateien zur Indexierung hochzuladen.

  3. Verwenden Sie items.index, um das Element zu indexieren. Wenn für das Schema beispielsweise die Objektdefinition aus dem Filmschema verwendet wird, würde eine Indexierungsanforderung für ein einzelnes Element so aussehen:

    {
      "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. Optional: Verwenden Sie items.get-Aufrufe, um zu prüfen, ob ein Element indexiert wurde.

Für einen vollständigen Durchlauf würden Sie das gesamte Repository regelmäßig neu indexieren. Für einen List Traversal oder Graph Traversal, müssen Sie Code für den Umgang mit Repository-Änderungen implementieren.

Umgang mit Repository-Änderungen

Sie können jedes Element regelmäßig aus einem Repository abrufen und indexieren, um eine vollständige Indexierung durchzuführen. Eine vollständige Indexierung kann zwar effektiv dafür sorgen, dass Ihr Index auf dem neuesten Stand ist, kann aber kostspielig sein, wenn sie mit größeren oder hierarchischen Repositories zu tun hat.

Anstatt ein gesamtes Repository regelmäßig mit Indexaufrufen zu indexieren, können Sie auch die Google Cloud-Indexierungswarteschlange verwenden, um Änderungen nachzuverfolgen und nur geänderte Elemente zu indexieren. Mit items.push-Anfragen können Sie der Warteschlange Elemente für spätere Abfragen und Updates hinzufügen. Weitere Informationen zur Google Cloud-Indexierungswarteschlange finden Sie unter Google Cloud-Indexierungswarteschlange.

Weitere Informationen zur Google Cloud Search API finden Sie unter Cloud Search API.