Crea un conector de contenido

Un conector de contenido es un programa de software usado para desviar los datos en un repositorio de una empresa y propagar una fuente de datos. Google brinda las siguientes opciones para desarrollar conectores de contenido:

  • El SDK de Content Connector Esta es una buena opción si programas en Java. El SDK de Content Connector es un wrapper alrededor de la API de REST que te permite crear conectores rápidamente. Para crear un conector de contenido mediante el uso del SDK, consulta Crea un conector de contenido con el SDK de Content Connector.

  • Una API de REST de bajo nivel o bibliotecas de la API. Usa estas opciones si no programas en Java, o si tu base de código se adapta mejor a una API de REST o a una biblioteca. Para crear un conector de contenido con la API de REST, consulta Crea un conector de contenido con la API de REST.

Un conector de contenido típico realiza las siguientes tareas:

  1. Lee y procesa parámetros de configuración.
  2. Extrae fragmentos discretos de datos indexables, llamados "elementos", del repositorio de contenido de terceros.
  3. Combina LCA, metadatos y datos de contenido en elementos indexables.
  4. Indexa elementos a la fuente de datos de Cloud Search.
  5. (opcional) Presta atención a las notificaciones de cambios del repositorio de contenido de terceros. Las notificaciones de cambios se convierten en solicitudes de indexación para mantener la fuente de datos de Cloud Search en sincronización con el repositorio de terceros. El conector solo realiza esta tarea si el repositorio es compatible con la detección de cambios.

Crea un conector de contenido con el SDK de Content Connector

En las siguientes secciones, se explica cómo crear un conector de contenido con el SDK de Content Connector.

Configura dependencias

Debes incluir determinadas dependencias en el archivo de compilación para usar el SDK. Haz clic en la pestaña a continuación para ver las dependencias del entorno de compilación:

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'

Crea tu configuración del conector

Cada conector tiene un archivo de configuración que contiene los parámetros que usa el conector, como el ID de tu repositorio. Los parámetros se definen como pares clave-valor, como api.sourceId=1234567890abcdef.

El SDK de Google Cloud Search contiene varios parámetros de configuración proporcionados por Google que son usados por todos los conectores. Debes declarar los siguientes parámetros proporcionados por Google en tu archivo de configuración:

  • Para un conector de contenido, debes declarar api.sourceId y api.serviceAccountPrivateKeyFile, ya que estos parámetros identifican la ubicación de tu repositorio y la clave privada necesarias para acceder al repositorio.
  • Para un conector de identidad, debes declarar api.identitySourceId, ya que este parámetro identifica la ubicación de la fuente de identidad externa. Si sincronizas usuarios, también debes declarar api.customerId como el ID único para la cuenta de Google Workspace de tu empresa.

A menos que desees anular los valores predeterminados de otros parámetros proporcionados por Google, no necesitas declararlos en el archivo de configuración. Para obtener información adicional sobre los parámetros de configuración proporcionados por Google, como la forma de generar determinados ID y claves, consulta Parámetros de configuración proporcionados por Google.

También puedes definir tus propios parámetros específicos del repositorio para usar en tu archivo de configuración.

Pasa el archivo de configuración al conector

Configura la propiedad del sistema config para pasar el archivo de configuración al conector. Puedes configurar la propiedad con el argumento -D cuando inicies el conector. Por ejemplo, el siguiente comando inicia el conector con el archivo de configuración MyConfig.properties:

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

Si falta este argumento, el SDK intenta acceder a un archivo de configuración predeterminado denominado connector-config.properties.

Determina tu estrategia de recorrido

La función primaria de un conector de contenido es recorrer un repositorio y luego indexar sus datos. Debes implementar una estrategia de recorrido en función del tamaño y diseño de los datos en tu repositorio. Puedes diseñar tu propia estrategia o elige entre las siguientes estrategias implementadas en el SDK:

Estrategia de recorrido completo

Una estrategia de recorrido completo analiza todo el repositorio e indexa a ciegas cada elemento. Esta estrategia se usa comúnmente cuando tienes un repositorio pequeño y puedes permitirte la sobrecarga de realizar un recorrido completo cada vez que indexas.

Esta estrategia de recorrido es adecuada para repositorios pequeños con datos mayormente estáticos y no jerárquicos. También puedes usar esta estrategia de recorrido cuando la detección de cambios es difícil o no es compatible con el repositorio.

Estrategia de recorrido de lista

Una estrategia de recorrido de lista analiza todo el repositorio, incluidos los nodos secundarios, y determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos que son nuevos o que se actualizaron desde la última indexación. Esta estrategia se usa comúnmente para realizar actualizaciones graduales en un índice existente (en lugar de tener que hacer un recorrido completo cada vez que actualizas el índice).

Esta estrategia de recorrido es adecuada cuando la detección de cambios es difícil o no es compatible con el repositorio, cuando tienes datos no jerárquicos y cuando estás trabajando con conjuntos de datos muy grandes.

Recorrido de gráfico

Una estrategia de recorrido de grafos analiza todo el nodo principal y determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos en el nodo raíz que son nuevos o que se actualizaron desde la última indexación. Por último, el conector pasa cualquier ID secundario e indexa elementos en los nodos secundarios que son nuevos o que se actualizaron. El conector continúa recursivamente a través de todos los nodos secundarios hasta que se hayan abordado todos los elementos. Este recorrido se usa normalmente para los repositorios jerárquicos donde no es práctico hacer una lista de todos los ID.

Esta estrategia es adecuada si tienes datos jerárquicos que deben ser rastreados, como una serie de directorios o páginas web.

Cada una de estas estrategias de recorrido se implementa mediante una clase de conector de plantilla en el SDK. Si bien puedes implementar tu propia estrategia de recorrido, estas plantillas aceleran en gran medida el desarrollo de tu conector. Para crear un conector mediante el uso de una plantilla, consulta la sección correspondiente a tu estrategia de recorrido:

Crea un conector de recorrido completo mediante el uso de una clase de plantilla

Esta sección de los documentos hace referencia a los fragmentos de código del ejemplo FullTraversalSample.

Implementa el punto de entrada del conector

El punto de entrada a un conector es el método main(). La tarea principal de este método es crear una instancia de la clase Application e invocar su método start() para ejecutar el conector.

Antes de llamar a application.start(), usa la clase IndexingApplication.Builder para crear una instancia de la plantilla FullTraversalConnector. FullTraversalConnector acepta un objeto Repository cuyos métodos implementarás. En el siguiente fragmento de código, se muestra cómo implementar el método 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();
}

En segundo plano, el SDK llama al método initConfig() después de que el método main() de tu conector llama a Application.build. El método initConfig() realiza las siguientes tareas:

  1. Llama al método Configuation.isInitialized() para asegurarse de que no se haya inicializado Configuration.
  2. Inicializa un objeto Configuration con los pares clave-valor proporcionados por Google. Cada par clave-valor se almacena en un objeto ConfigValue dentro del objeto Configuration.

Implementa la interfaz Repository

El único propósito del objeto Repository es realizar el recorrido y la indexación de los elementos del repositorio. Cuando usas una plantilla, solo debes anular ciertos métodos dentro de la interfaz Repository para crear un conector de contenido. Los métodos que anulas dependen de la plantilla y de la estrategia de recorrido que usas. En el caso de FullTraversalConnector, anula los siguientes métodos:

  • El método init(). Para realizar cualquier inicialización y configuración del repositorio de datos, anula el método init().

  • El método getAllDocs(). Para indexar y recorrer todos los elementos en el repositorio de datos, anula el método getAllDocs(). Se llama a este método una vez por cada recorrido programado (según lo define tu configuración).

  • getChanges() (opcional): Si tu repositorio es compatible con la detección de cambios, anula el método getChanges(). Se llama a este método una vez por cada recorrido gradual programado (según lo define tu configuración) para recuperar elementos modificados y luego indexarlos.

  • close() (opcional): Si tienes que hacer una limpieza del repositorio, anula el método close(). Se llama a este método una vez durante el cierre del conector.

Cada uno de los métodos del objeto Repository muestra algún tipo de objeto ApiOperation. Un objeto ApiOperation realiza acciones en forma de una llamada (o quizás varias) a IndexingService.indexItem() para realizar la indexación real de tu repositorio.

Obtén parámetros de configuración personalizados

Como parte del control de la configuración del conector, deberás obtener los parámetros personalizados del objeto Configuration. Por lo general, esta tarea se realiza en el método init() de una clase Repository.

La clase Configuration tiene varios métodos para obtener tipos de datos diferentes de una configuración. Cada método muestra un objeto ConfigValue. Luego, usa el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un solo valor de número entero personalizado de un objeto Configuration:

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

Para obtener y analizar un parámetro que contenga varios valores, usa uno de los analizadores de tipos de la clase Configuration para analizar los datos en fragmentos separados. En el siguiente fragmento del conector del instructivo, se usa el método getMultiValue para obtener una lista de nombres de repositorios de GitHub:

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

Realiza un recorrido completo

Anula getAllDocs() para realizar un recorrido completo y, luego, indexar tu repositorio. El método getAllDocs() acepta un punto de control. El punto de control se usa para reanudar la indexación en un elemento específico en caso de que se interrumpa el proceso. Para cada elemento en tu repositorio, sigue estos pasos en el método getAllDocs():

  1. Establece permisos.
  2. Establece los metadatos para el elemento que indexas.
  3. Combina los metadatos y el elemento en un RepositoryDoc indexable.
  4. Empaqueta cada elemento indexable en un iterador que muestra el método getAllDocs(). Ten en cuenta que getAllDocs(), en realidad, muestra un CheckpointCloseableIterable, que es una iteración de objetos ApiOperation, cada uno de los cuales representa una solicitud a la API que se realiza en un RepositoryDoc, como indexarlo.

Si el conjunto de elementos es demasiado grande para procesarse en una sola llamada, incluye un punto de control y establece hasMore(true) para indicar que hay más elementos disponibles para indexar.

Establece los permisos para un elemento

Tu repositorio usa una Lista de control de acceso (LCA) para identificar los usuarios o grupos que tienen acceso a un elemento. Una LCA es una lista de ID para grupos o usuarios que pueden acceder al elemento.

Debes duplicar la LCA que usa tu repositorio para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de la búsqueda. La LCA de un elemento debe incluirse cuando se indexa el elemento, a fin de que Google Cloud Search tenga la información que necesita para proporcionar el nivel correcto de acceso al elemento.

El SDK de Content Connector proporciona un amplio conjunto de métodos y clases de LCA para modelar las LCA de la mayoría de los repositorios. Debes analizar la LCA para cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si tu LCA del repositorio emplea conceptos como la herencia de la LCA, modelar esa LCA puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search es compatible con las LCA de un solo dominio. No es compatible con las LCA de dominio cruzado. Usa la clase Acl.Builder para establecer el acceso a cada elemento con una LCA. El siguiente fragmento de código, tomado del ejemplo de recorrido completo, permite que todos los usuarios o "principales" (getCustomerPrincipal()) sean "lectores" de todos los elementos (.setReaders()) cuando realizan una búsqueda.

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

Debes comprender las LCA para modelarlas de manera adecuada para el repositorio. Por ejemplo, podrías estar indexando archivos dentro de un sistema de archivos que usa algún tipo de modelo de herencia por el cual las carpetas secundarias heredan permisos de las carpetas principales. El modelado de la herencia de LCA requiere información adicional incluida en las LCA de Google Cloud Search

Establece los metadatos de un elemento

Los metadatos se almacenan en un objeto Item. Para crear un Item, necesitas un mínimo de ID de cadena único, un tipo de elemento, una LCA, una URL y una versión para el elemento. En el siguiente fragmento de código, se muestra cómo compilar un Item con la clase auxiliar IndexingItemBuilder.

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

Crea el elemento indexable

Una vez que hayas configurado los metadatos para el elemento, puedes crear el elemento indexable real mediante la clase RepositoryDoc.Builder. En el siguiente ejemplo, se muestra cómo crear un elemento indexable único.

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

Un RepositoryDoc es un tipo de ApiOperation que realiza la solicitud IndexingService.indexItem() real.

También puedes usar el método setRequestMode() de la clase RepositoryDoc.Builder para identificar la solicitud de indexación como ASYNCHRONOUS o SYNCHRONOUS:

ASYNCHRONOUS
El modo asíncrono genera una latencia de indexación a entrega más prolongada y se adapta a una gran cuota de capacidad de procesamiento para las solicitudes de indexación. Se recomienda el modo asíncrono para la indexación inicial (reabastecimiento) de todo el repositorio.
SYNCHRONOUS
El modo síncrono da como resultado una latencia de indexación a entrega más corta y se adapta a una cuota de capacidad de procesamiento limitada. Se recomienda el modo síncrono para la indexación de actualizaciones y cambios en el repositorio. Si no se especifica, el modo de solicitud predeterminado es SYNCHRONOUS.

Empaqueta cada elemento indexable en un iterador

El método getAllDocs() muestra un Iterator, específicamente un CheckpointCloseableIterable, de objetos RepositoryDoc. Puedes usar la clase CheckpointClosableIterableImpl.Builder para construir y mostrar un iterador. El siguiente fragmento de código muestra cómo construir y mostrar un iterador.

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

El SDK ejecuta cada llamada de indexación incluida dentro del iterador.

Próximos pasos

Aquí hay algunos pasos que puedes seguir:

Crea un conector de recorrido de lista mediante el uso de una clase de plantilla

La cola de indexación de Cloud Search se usa para almacenar ID y valores hash opcionales para cada elemento en el repositorio. Un conector de recorrido de lista envía los ID de elementos a la cola de indexación de Google Cloud Search y los recupera uno por uno para la indexación. Google Cloud Search mantiene colas y compara contenidos de cola para determinar el estado del elemento, por ejemplo, si un elemento se ha borrado del repositorio. Para obtener más información sobre la cola de indexación de Cloud Search, consulta La cola de indexación de Cloud Search.

Esta sección de los documentos hace referencia a los fragmentos de código del ejemplo ListTraversalSample.

Implementa el punto de entrada del conector

El punto de entrada a un conector es el método main(). La tarea principal de este método es crear una instancia de la clase Application e invocar su método start() para ejecutar el conector.

Antes de llamar a application.start(), usa la clase IndexingApplication.Builder para crear una instancia de la plantilla ListingConnector. ListingConnector acepta un objeto Repository cuyos métodos implementarás. En el siguiente fragmento, se muestra cómo crear una instancia de ListingConnector y su Repository asociado:

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

En segundo plano, el SDK llama al método initConfig() después de que el método main() de tu conector llama a Application.build. El método initConfig():

  1. Llama al método Configuation.isInitialized() para asegurarse de que no se haya inicializado Configuration.
  2. Inicializa un objeto Configuration con los pares clave-valor proporcionados por Google. Cada par clave-valor se almacena en un objeto ConfigValue dentro del objeto Configuration.

Implementa la interfaz Repository

El único propósito del objeto Repository es realizar el recorrido y la indexación de los elementos del repositorio. Cuando usas una plantilla, solo debes anular ciertos métodos dentro de la interfaz Repository para crear un conector de contenido. Los métodos que anules dependerán de la plantilla y de la estrategia de recorrido que uses. En el caso de ListingConnector, anula los siguientes métodos:

  • El método init(). Para realizar cualquier inicialización y configuración del repositorio de datos, anula el método init().

  • El método getIds(). Para recuperar los ID y los valores hash para todos los registros en el repositorio, anula el método getIds().

  • El método getDoc(). Para agregar elementos nuevos, actualizarlos, modificarlos o borrarlos de un índice, anula el método getDoc().

  • getChanges() (opcional): Si tu repositorio es compatible con la detección de cambios, anula el método getChanges(). Se llama a este método una vez por cada recorrido gradual programado (según lo define tu configuración) para recuperar elementos modificados y luego indexarlos.

  • close() (opcional): Si tienes que hacer una limpieza del repositorio, anula el método close(). Se llama a este método una vez durante el cierre del conector.

Cada uno de los métodos del objeto Repository muestra algún tipo de objeto ApiOperation. Un objeto ApiOperation realiza acciones en forma de una llamada (o quizás varias) a IndexingService.indexItem() para realizar la indexación real de tu repositorio.

Obtén parámetros de configuración personalizados

Como parte del control de la configuración del conector, deberás obtener los parámetros personalizados del objeto Configuration. Por lo general, esta tarea se realiza en el método init() de una clase Repository.

La clase Configuration tiene varios métodos para obtener tipos de datos diferentes de una configuración. Cada método muestra un objeto ConfigValue. Luego, usa el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un solo valor de número entero personalizado de un objeto Configuration:

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

Para obtener y analizar un parámetro que contenga varios valores, usa uno de los analizadores de tipos de la clase Configuration para analizar los datos en fragmentos separados. En el siguiente fragmento del conector del instructivo, se usa el método getMultiValue para obtener una lista de nombres de repositorios de GitHub:

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

Realiza el recorrido de lista

Anula el método getIds() para recuperar los ID y los valores hash de todos los registros del repositorio. El método getIds() acepta un punto de control. El punto de control se usa para reanudar la indexación en un elemento específico en caso de que se interrumpa el proceso.

A continuación, anula el método getDoc() para controlar cada elemento de la cola de indexación de Cloud Search.

Envía ID de elementos y valores hash

Anula getIds() para recuperar los IDs de los elementos y los valores hash de su contenido asociado del repositorio. Los ID y pares de valor hash luego se empaquetan en una solicitud de operación push a la cola de indexación de Cloud Search. Por lo general, los ID principales o de raíz se envían primero, seguidos por los ID secundarios hasta que se haya procesado toda la jerarquía de elementos.

El método getIds() acepta un punto de control que representa el último elemento que se indexará. El punto de control se puede usar para reanudar la indexación en un elemento específico en caso de que se interrumpa el proceso. Para cada elemento en tu repositorio, sigue estos pasos en el método getIds():

  • Obtén cada ID de elemento y el valor hash asociado del repositorio.
  • Empaqueta cada ID y par de valor hash en un PushItems.
  • Combina cada PushItems en un iterador que muestra el método getIds(). Ten en cuenta que getIds(), en realidad, muestra un CheckpointCloseableIterable, que es una iteración de objetos ApiOperation, cada uno de los cuales representa una solicitud a la API que se realiza en un RepositoryDoc, como enviar los elementos a la cola.

En el siguiente fragmento de código, se muestra cómo obtener cada ID de elemento y valor hash, y, luego, insertarlos en un PushItems. Un PushItems es una solicitud ApiOperation para enviar un elemento a la cola de indexación de Cloud Search.

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

En el siguiente fragmento de código, se muestra cómo usar la clase PushItems.Builder para empaquetar los IDs y los valores hash en un solo ApiOperation de push.

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

Los elementos se envían a la cola de indexación de Cloud Search para su posterior procesamiento.

Recupera y controla cada elemento

Anula getDoc() para controlar cada elemento de la cola de indexación de Cloud Search. Un elemento puede ser nuevo, modificado o sin cambios, o puede no existir más en el repositorio de código fuente. Recupera e indexa cada elemento que sea nuevo o modificado. Quita los elementos del índice que ya no existen en el repositorio de código fuente.

El método getDoc() acepta un elemento de la cola de indexación de Google Cloud Search. Para cada elemento en la cola, sigue estos pasos en el método getDoc():

  1. Comprueba si el ID del elemento, dentro de la cola de indexación de Cloud Search, existe en el repositorio. Si no existe, borra el elemento del índice.

  2. Consulta el índice para el estado del elemento y, si un elemento no ha sido modificado (ACCEPTED), no hagas nada.

  3. Índice modificado o elementos nuevos:

    1. Configura los permisos.
    2. Establece los metadatos para el elemento que indexas.
    3. Combina los metadatos y el elemento en un RepositoryDoc indexable.
    4. Muestra RepositoryDoc.

Nota: La plantilla ListingConnector no admite mostrar null en el método getDoc(). Cómo mostrar null en un NullPointerException.

Controla los elementos borrados

El siguiente fragmento de código muestra cómo determinar si un elemento existe en el repositorio y, si no, cómo borrarlo.

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

Ten en cuenta que documents es una estructura de datos que representa el repositorio. Si no se encuentra documentID en documents, muestra APIOperations.deleteItem(resourceName) para borrar el elemento del índice.

Controla elementos no modificados

El siguiente fragmento de código muestra cómo consultar el estado del elemento en la cola de indexación de Cloud Search y controlar un elemento no modificado.

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

Para determinar si un elemento no está modificado, verifica el estado del elemento, así como otros metadatos que pueden indicar un cambio. En el ejemplo, el hash de los metadatos se usa para determinar si el elemento se ha modificado.

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

Configura los permisos para un elemento

Tu repositorio usa una Lista de control de acceso (LCA) para identificar los usuarios o grupos que tienen acceso a un elemento. Una LCA es una lista de ID para grupos o usuarios que pueden acceder al elemento.

Debes duplicar la LCA que usa tu repositorio para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de la búsqueda. La LCA de un elemento debe incluirse cuando se indexa el elemento, a fin de que Google Cloud Search tenga la información que necesita para proporcionar el nivel correcto de acceso al elemento.

El SDK de Content Connector proporciona un amplio conjunto de métodos y clases de LCA para modelar las LCA de la mayoría de los repositorios. Debes analizar la LCA para cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si tu LCA del repositorio emplea conceptos como la herencia de la LCA, modelar esa LCA puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search es compatible con las LCA de un solo dominio. No es compatible con las LCA de dominio cruzado. Usa la clase Acl.Builder para establecer el acceso a cada elemento con una LCA. El siguiente fragmento de código, tomado del ejemplo de recorrido completo, permite que todos los usuarios o "principales" (getCustomerPrincipal()) sean "lectores" de todos los elementos (.setReaders()) cuando realizan una búsqueda.

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

Debes comprender las LCA para modelarlas de manera adecuada para el repositorio. Por ejemplo, podrías estar indexando archivos dentro de un sistema de archivos que usa algún tipo de modelo de herencia por el cual las carpetas secundarias heredan permisos de las carpetas principales. El modelado de la herencia de LCA requiere información adicional incluida en las LCA de Google Cloud Search

Establece los metadatos de un elemento

Los metadatos se almacenan en un objeto Item. Para crear un Item, necesitas un mínimo de ID de cadena único, un tipo de elemento, una LCA, una URL y una versión para el elemento. En el siguiente fragmento de código, se muestra cómo compilar un Item con la clase auxiliar IndexingItemBuilder.

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

Crea un elemento indexable

Una vez que hayas configurado los metadatos para el elemento, puedes crear el elemento indexable real mediante RepositoryDoc.Builder. En el siguiente ejemplo, se muestra cómo crear un elemento indexable único.

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

Un RepositoryDoc es un tipo de ApiOperation que realiza la solicitud IndexingService.indexItem() real.

También puedes usar el método setRequestMode() de la clase RepositoryDoc.Builder para identificar la solicitud de indexación como ASYNCHRONOUS o SYNCHRONOUS:

ASYNCHRONOUS
El modo asíncrono genera una latencia de indexación a entrega más prolongada y se adapta a una gran cuota de capacidad de procesamiento para las solicitudes de indexación. Se recomienda el modo asíncrono para la indexación inicial (reabastecimiento) de todo el repositorio.
SYNCHRONOUS
El modo síncrono da como resultado una latencia de indexación a entrega más corta y se adapta a una cuota de capacidad de procesamiento limitada. Se recomienda el modo síncrono para la indexación de actualizaciones y cambios en el repositorio. Si no se especifica, el modo de solicitud predeterminado es SYNCHRONOUS.

Próximos pasos

Aquí hay algunos pasos que puedes seguir:

  • Implementa el método close() para liberar cualquier recurso antes de finalizar el procedimiento (opcional).
  • Crea un conector de identidad mediante el SDK de Content Connector (opcional).

Crea un conector de recorrido de grafo mediante el uso de una clase de plantilla

La cola de indexación de Cloud Search se usa para almacenar ID y valores hash opcionales para cada elemento en el repositorio. Un conector de recorrido de grafo envía los IDs de elementos a la cola de indexación de Google Cloud Search y los recupera uno por uno para la indexación. Google Cloud Search mantiene colas y compara contenidos de cola para determinar el estado del elemento, por ejemplo, si un elemento se ha borrado del repositorio. Para obtener más información sobre la cola de indexación de Cloud Search, consulta La cola de indexación de Google Cloud Search.

Durante el índice, el contenido del elemento se recupera del repositorio de datos y cualquier ID del elemento secundario se envía a la cola. El conector continúa procesando recursivamente los ID principales y secundarios hasta que se controlan todos los elementos.

Esta sección de los documentos hace referencia a los fragmentos de código del ejemplo GraphTraversalSample.

Implementa el punto de entrada del conector

El punto de entrada a un conector es el método main(). La tarea principal de este método es crear una instancia de la clase Application e invocar su método start() para ejecutar el conector.

Antes de llamar a application.start(), usa la clase IndexingApplication.Builder para crear una instancia de la plantilla ListingConnector. ListingConnector acepta un objeto Repository cuyos métodos implementarás.

En el siguiente fragmento, se muestra cómo crear una instancia de ListingConnector y su Repository asociado:

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

En segundo plano, el SDK llama al método initConfig() después de que el método main() de tu conector llama a Application.build. El método initConfig():

  1. Llama al método Configuation.isInitialized() para asegurarse de que no se haya inicializado Configuration.
  2. Inicializa un objeto Configuration con los pares clave-valor proporcionados por Google. Cada par clave-valor se almacena en un objeto ConfigValue dentro del objeto Configuration.

Implementa la interfaz Repository

El único propósito del objeto Repository es realizar el recorrido y la indexación de los elementos del repositorio. Cuando usas una plantilla, solo debes anular ciertos métodos dentro de la interfaz Repository para crear un conector de contenido. Los métodos que anulas dependen de la plantilla y de la estrategia de recorrido que usas. En el caso de ListingConnector, anula los siguientes métodos:

  • El método init(). Para realizar cualquier inicialización y configuración del repositorio de datos, anula el método init().

  • El método getIds(). Para recuperar los ID y los valores hash para todos los registros en el repositorio, anula el método getIds().

  • El método getDoc(). Para agregar elementos nuevos, actualizarlos, modificarlos o borrarlos de un índice, anula el método getDoc().

  • getChanges() (opcional): Si tu repositorio es compatible con la detección de cambios, anula el método getChanges(). Se llama a este método una vez por cada recorrido gradual programado (según lo define tu configuración) para recuperar elementos modificados y luego indexarlos.

  • close() (opcional): Si tienes que hacer una limpieza del repositorio, anula el método close(). Se llama a este método una vez durante el cierre del conector.

Cada uno de los métodos del objeto Repository muestra algún tipo de objeto ApiOperation. Un objeto ApiOperation realiza acciones en forma de una llamada (o varias) a IndexingService.indexItem() para llevar a cabo la indexación real de tu repositorio.

Obtén parámetros de configuración personalizados

Como parte del control de la configuración del conector, deberás obtener los parámetros personalizados del objeto Configuration. Por lo general, esta tarea se realiza en el método init() de una clase Repository.

La clase Configuration tiene varios métodos para obtener tipos de datos diferentes de una configuración. Cada método muestra un objeto ConfigValue. Luego, usa el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un solo valor de número entero personalizado de un objeto Configuration:

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

Para obtener y analizar un parámetro que contenga varios valores, usa uno de los analizadores de tipos de la clase Configuration para analizar los datos en fragmentos separados. En el siguiente fragmento del conector del instructivo, se usa el método getMultiValue para obtener una lista de nombres de repositorios de GitHub:

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

Realiza el recorrido de grafo

Anula el método getIds() para recuperar los ID y los valores hash de todos los registros del repositorio. El método getIds() acepta un punto de control. El punto de control se usa para reanudar la indexación en un elemento específico en caso de que se interrumpa el proceso.

A continuación, anula el método getDoc() para controlar cada elemento de la cola de indexación de Cloud Search.

Envía ID de elementos y valores hash

Anula getIds() para recuperar los IDs de los elementos y los valores hash de su contenido asociado del repositorio. Los ID y pares de valor hash luego se empaquetan en una solicitud de operación push a la cola de indexación de Cloud Search. Por lo general, los ID principales o de raíz se envían primero, seguidos por los ID secundarios hasta que se haya procesado toda la jerarquía de elementos.

El método getIds() acepta un punto de control que representa el último elemento que se indexará. El punto de control se puede usar para reanudar la indexación en un elemento específico en caso de que se interrumpa el proceso. Para cada elemento en tu repositorio, sigue estos pasos en el método getIds():

  • Obtén cada ID de elemento y el valor hash asociado del repositorio.
  • Empaqueta cada ID y par de valor hash en un PushItems.
  • Combina cada PushItems en un iterador que muestra el método getIds(). Ten en cuenta que getIds(), en realidad, muestra un CheckpointCloseableIterable, que es una iteración de objetos ApiOperation, cada uno de los cuales representa una solicitud a la API que se realiza en un RepositoryDoc, como enviar los elementos a la cola.

En el siguiente fragmento de código, se muestra cómo obtener cada ID de elemento y valor hash, y, luego, insertarlos en un PushItems. Un PushItems es una solicitud a ApiOperation para enviar un elemento a la cola de indexación de Cloud Search.

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

En el siguiente fragmento de código, se muestra cómo usar la clase PushItems.Builder para empaquetar los IDs y los valores hash en un solo elemento ApiOperation de push.

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

Los elementos se envían a la cola de indexación de Cloud Search para su posterior procesamiento.

Recupera y controla cada elemento

Anula getDoc() para controlar cada elemento de la cola de indexación de Cloud Search. Un elemento puede ser nuevo, modificado o sin cambios, o puede no existir más en el repositorio de código fuente. Recupera e indexa cada elemento que sea nuevo o modificado. Quita los elementos del índice que ya no existen en el repositorio de código fuente.

El método getDoc() acepta un elemento de la cola de indexación de Cloud Search. Para cada elemento en la cola, sigue estos pasos en el método getDoc():

  1. Comprueba si el ID del elemento, dentro de la cola de indexación de Cloud Search, existe en el repositorio. Si no, borra el elemento del índice. Si el elemento existe, sigue con el próximo paso.

  2. Índice modificado o elementos nuevos:

    1. Configura los permisos.
    2. Establece los metadatos para el elemento que indexas.
    3. Combina los metadatos y el elemento en un RepositoryDoc indexable.
    4. Coloca los ID secundarios en la cola de indexación de Cloud Search para su posterior procesamiento.
    5. Muestra RepositoryDoc.

Controla los elementos borrados

El siguiente fragmento de código muestra cómo determinar si un elemento existe en el índice y, si no, cómo borrarlo.

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

Configura los permisos para un elemento

Tu repositorio usa una Lista de control de acceso (LCA) para identificar los usuarios o grupos que tienen acceso a un elemento. Una LCA es una lista de ID para grupos o usuarios que pueden acceder al elemento.

Debes duplicar la LCA que usa tu repositorio para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de la búsqueda. La LCA de un elemento debe incluirse cuando se indexa el elemento, a fin de que Google Cloud Search tenga la información que necesita para proporcionar el nivel correcto de acceso al elemento.

El SDK de Content Connector proporciona un amplio conjunto de métodos y clases de LCA para modelar las LCA de la mayoría de los repositorios. Debes analizar la LCA para cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si tu LCA del repositorio emplea conceptos como la herencia de la LCA, modelar esa LCA puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search es compatible con las LCA de un solo dominio. No es compatible con las LCA de dominio cruzado. Usa la clase Acl.Builder para establecer el acceso a cada elemento con una LCA. El siguiente fragmento de código, tomado del ejemplo de recorrido completo, permite que todos los usuarios o "principales" (getCustomerPrincipal()) sean "lectores" de todos los elementos (.setReaders()) cuando realizan una búsqueda.

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

Debes comprender las LCA para modelarlas de manera adecuada para el repositorio. Por ejemplo, podrías estar indexando archivos dentro de un sistema de archivos que usa algún tipo de modelo de herencia por el cual las carpetas secundarias heredan permisos de las carpetas principales. El modelado de la herencia de LCA requiere información adicional incluida en las LCA de Google Cloud Search

Establece los metadatos de un elemento

Los metadatos se almacenan en un objeto Item. Para crear un Item, necesitas un mínimo de ID de cadena único, un tipo de elemento, una LCA, una URL y una versión para el elemento. En el siguiente fragmento de código, se muestra cómo compilar un Item con la clase auxiliar IndexingItemBuilder.

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

Crea el elemento indexable

Una vez que hayas configurado los metadatos para el elemento, puedes crear el elemento indexable real mediante RepositoryDoc.Builder. En el siguiente ejemplo, se muestra cómo crear un elemento indexable único.

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

Un RepositoryDoc es un tipo de ApiOperation que realiza la solicitud IndexingService.indexItem() real.

También puedes usar el método setRequestMode() de la clase RepositoryDoc.Builder para identificar la solicitud de indexación como ASYNCHRONOUS o SYNCHRONOUS:

ASYNCHRONOUS
El modo asíncrono genera una latencia de indexación a entrega más prolongada y se adapta a una gran cuota de capacidad de procesamiento para las solicitudes de indexación. Se recomienda el modo asíncrono para la indexación inicial (reabastecimiento) de todo el repositorio.
SYNCHRONOUS
El modo síncrono da como resultado una latencia de indexación a entrega más corta y se adapta a una cuota de capacidad de procesamiento limitada. Se recomienda el modo síncrono para la indexación de actualizaciones y cambios en el repositorio. Si no se especifica, el modo de solicitud predeterminado es SYNCHRONOUS.

Coloca los ID secundarios en la cola de indexación de Cloud Search

El siguiente fragmento de código muestra cómo incluir los ID secundarios, para el elemento principal que se procesa actualmente, en la cola para su procesamiento. Estos ID se procesan después de que se indexa el elemento principal.

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

Próximos pasos

Aquí hay algunos pasos que puedes seguir:

  • Implementa el método close() para liberar cualquier recurso antes de finalizar el procedimiento (opcional).
  • (opcional) Crea un conector de identidad con el uso del SDK de Identity Connector.

Crea un conector de contenido con la API de REST

Las siguientes secciones explican cómo crear un conector de contenido con la API de REST.

Determina tu estrategia de recorrido

La función primaria de un conector de contenido es recorrer un repositorio y luego indexar sus datos. Debes implementar una estrategia de recorrido en función del tamaño y diseño de los datos en tu repositorio. Las siguientes son tres estrategias de recorrido comunes:

Estrategia de recorrido completo

Una estrategia de recorrido completo analiza todo el repositorio e indexa a ciegas cada elemento. Esta estrategia se usa comúnmente cuando tienes un repositorio pequeño y puedes permitirte la sobrecarga de realizar un recorrido completo cada vez que indexas.

Esta estrategia de recorrido es adecuada para repositorios pequeños con datos mayormente estáticos y no jerárquicos. También puedes usar esta estrategia de recorrido cuando la detección de cambios es difícil o no es compatible con el repositorio.

Estrategia de recorrido de lista

Una estrategia de recorrido de lista analiza todo el repositorio, incluidos los nodos secundarios, y determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos que son nuevos o que se actualizaron desde la última indexación. Esta estrategia se usa comúnmente para realizar actualizaciones graduales en un índice existente (en lugar de tener que hacer un recorrido completo cada vez que actualizas el índice).

Esta estrategia de recorrido es adecuada cuando la detección de cambios es difícil o no es compatible con el repositorio, cuando tienes datos no jerárquicos y cuando estás trabajando con conjuntos de datos muy grandes.

Recorrido de gráfico

Una estrategia de recorrido de grafos analiza todo el nodo principal y determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos en el nodo raíz que son nuevos o que se actualizaron desde la última indexación. Por último, el conector pasa cualquier ID secundario e indexa elementos en los nodos secundarios que son nuevos o que se actualizaron. El conector continúa recursivamente a través de todos los nodos secundarios hasta que se hayan abordado todos los elementos. Este recorrido se usa normalmente para los repositorios jerárquicos donde no es práctico hacer una lista de todos los ID.

Esta estrategia es adecuada si tienes datos jerárquicos que deben ser rastreados, como una serie de directorios o páginas web.

Implementa tu estrategia de recorrido y los elementos de índice

Cada elemento indexable para Cloud Search se conoce como un elemento en la API de Cloud Search. Un elemento puede ser un archivo, una carpeta, una línea en un archivo CSV o un registro de base de datos.

Una vez que se registra tu esquema, puedes propagar el índice de las siguientes maneras:

  1. items.upload a fin de subir archivos de más de 100 KiB para indexar (opcional). Para archivos más pequeños, incorpora el contenido como inlineContent con items.index.

  2. media.upload a fin de subir archivos multimedia para indexar (opcional).

  3. Mediante items.index, para indexar el elemento. Por ejemplo, si tu esquema usa la definición del objeto en el esquema de película, una solicitud de indexación para un solo elemento se vería así:

    {
      "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. Llamadas a items.get para verificar que se haya indexado un elemento (opcional).

Para realizar un recorrido completo, deberías volver a indexar periódicamente el repositorio completo. Si quieres realizar un recorrido de grafo o de lista, debes implementar código para controlar los cambios del repositorio.

Controla cambios de repositorio

Periódicamente, puedes reunir y además indexar cada elemento de un repositorio para realizar una indexación completa. Si bien es efectiva para garantizar que tu índice esté actualizado, una indexación completa puede ser costosa cuando se trata de repositorios jerárquicos o más grandes.

En lugar de usar llamadas al índice para indexar un repositorio completo de vez en cuando, también puedes usar la cola de indexación de Google Cloud como un mecanismo para hacer un seguimiento de los cambios y solo indexar aquellos elementos que han sido modificados. Puedes usar las solicitudes items.push para enviar elementos a la cola para consultarlos y actualizarlos más tarde. Para obtener más información sobre la cola de indexación de Google Cloud, consulta Cola de indexación de Google Cloud.

Para obtener más información sobre la API de Google Cloud Search, consulta la API de Cloud Search.