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 conector de contenido. Esta es una buena opción si programas en Java. El SDK de conector de contenido es un wrapper alrededor de la API de REST que te permite crear conectores con rapidez. Para crear un conector de contenido con el SDK, consulta Crear un conector de contenido con el SDK de conector de contenido.

  • Una API de REST de bajo nivel o bibliotecas de 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 una biblioteca. Para crear un conector de contenido con la API de REST, consulta Crear 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. Presta atención a las notificaciones de cambios del repositorio de contenido de terceros (opcional). Las notificaciones de cambios se convierten en solicitudes de indexación para mantener la fuente de datos de Cloud Search sincronizada 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 conector de contenido

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

Configura dependencias

Debes incluir determinadas dependencias en el archivo de compilación para usar el SDK. Haz clic en una de las siguientes pestañas a fin de 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 el siguiente:

api.sourceId=1234567890abcdef
.

El SDK de Google Cloud Search contiene varios parámetros de configuración proporcionados por Google que todos los conectores usan. 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 tu cuenta de G Suite de la empresa.

A menos que desees anular los valores predeterminados de otros parámetros proporcionados por Google, no debes 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 esta página sobre los parámetros de configuración proporcionados por Google.

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

Nota: No existe un requisito de denominación estricto para el archivo de propiedades del conector, pero recomendamos guardar el archivo con una extensión .properties o .config.

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 desviar contenido de 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 elegir entre las siguientes estrategias implementadas en el SDK:

Estrategia de recorrido completo

Con una estrategia de recorrido completo, se analiza todo el repositorio y, luego, se indexa a ciegas cada elemento. Esta estrategia se suele usar 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 que son, en su mayoría, 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

Con una estrategia de recorrido de lista, se analiza todo el repositorio, incluidos los nodos secundarios, y se determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos que sean nuevos o que se hayan actualizado desde la última indexación. Esta estrategia se suele usar 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, tienes datos no jerárquicos y trabajas con conjuntos de datos muy grandes.

Recorrido de grafos

Con una estrategia de recorrido de grafos, se analiza todo el nodo superior y se determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos en el nodo raíz que sean nuevos o que se hayan actualizado desde la última indexación. Por último, el conector pasa cualquier ID secundario y, luego, indexa elementos en los nodos secundarios que sean nuevos o se hayan actualizado. El conector continúa de manera recursiva a través de todos los nodos secundarios hasta que se abordan todos los elementos. Por lo general, este recorrido se usa para los repositorios jerárquicos en los que no es práctico hacer una lista de todos los ID.

Esta estrategia es adecuada si tienes datos jerárquicos que deben rastrearse, 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 con 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

En esta sección de los documentos, se 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 y, luego, 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. El FullTraversalConnector acepta un objeto Repository que contiene los métodos que 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() del conector llame a Application.build. El método initConfig() realiza las siguientes tareas:

  1. Llama al método Configuation.isInitialized() para garantizar que Configuration no se inicializó.
  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 FullTraversalConnector, anula los siguientes métodos:

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

  • getAllDocs(): para desviar y, luego, indexar 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 defina 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 defina tu configuración) para recuperar elementos modificados y, luego, indexarlos.

  • close() (opcional): si necesitas 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. Los objetos ApiOperation realizan acciones en forma de una llamada (o quizás 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. Usarás el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un único 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 a fin de 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 mostrado por el método getAllDocs(). Ten en cuenta que, en realidad, getAllDocs() muestra CheckpointCloseableIterable, que es una iteración de objetos ApiOperation. Cada objeto representa una solicitud a la API realizada en RepositoryDoc, como su indexación.

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

Establece los permisos para un elemento

El repositorio usa una Lista de control de acceso (LCA) para identificar a 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 esta LCA en la fuente de datos para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de búsqueda. Como tal, 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 a él.

El SDK de conector de contenido 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 de cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si la LCA del repositorio usa conceptos como la herencia de la LCA, modelarla puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta la sección sobre las LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search admite LCA de dominio único. No es compatible con LCA de dominio cruzado. Fundamentalmente, usarás la clase Acl.Builder para establecer el acceso a cada elemento mediante una LCA. En el siguiente fragmento de código, tomado de la muestra de recorrido completo, se permite a todos los usuarios o “principales” (getCustomerPrincipal()) ser “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();

Deberás comprender las LCA a fin de modelarlas de manera adecuada para la fuente de datos. Por ejemplo, podrías indexar archivos dentro de un sistema de archivos que use algún tipo de modelo de herencia mediante el que las carpetas secundarias hereden permisos de las carpetas superiores. Para modelar la herencia de LCA, se requiere información adicional incluida en la página sobre 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 como mínimo un ID de string ú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 mediante 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 este modo 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 este modo 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, en particular un CheckpointCloseableIterable, de objetos RepositoryDoc. Puedes usar la clase CheckpointClosableIterableImpl.Builder para crear y mostrar un iterador. En el siguiente fragmento de código, se muestra cómo crear 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.

Pasos siguientes

Aquí hay algunos pasos que puedes seguir:

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

La cola de indexación de Cloud Search se usa a fin de conservar 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 el contenido en ellas para determinar el estado de elementos, por ejemplo, si un elemento se borró del repositorio. Para obtener más información sobre la cola de indexación de Cloud Search, consulta la sección Cola de indexación de Google Cloud Search.

En esta sección de los documentos, se 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 y, luego, 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. El ListingConnector acepta un objeto Repository que contiene los métodos que implementarás. En el siguiente fragmento, se muestra cómo crear una instancia de ListingConnector y del 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() del conector llame a Application.build. El método initConfig() realiza las siguientes acciones:

  1. Llama al método Configuation.isInitialized() para garantizar que Configuration no se inicializó.
  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 uses 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:

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

  • getIds(): a fin de recuperar los ID y los valores hash para todos los registros en el repositorio, anula el método getIds().

  • 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 defina tu configuración) para recuperar elementos modificados y, luego, indexarlos.

  • close() (opcional): si necesitas 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. Los objetos ApiOperation realizan acciones en forma de una llamada (o quizás 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. Usarás el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un único 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 a fin de 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.

Luego 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 ID de los elementos y los valores hash de su contenido asociado del repositorio. Los ID y los pares de valores hash se empaquetan en una solicitud de operación push a la cola de indexación de Cloud Search. Por lo general, los ID superiores o raíz se envían primero, luego los ID secundarios, hasta que se procesa 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 de 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() muestra un CheckpointCloseableIterable, que es una iteración de objetos ApiOperation. Cada objeto representa una solicitud a la API realizada en un RepositoryDoc, como el envío de 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 cómo insertarlos en un PushItems. Un PushItems es una solicitud a 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 ID y los valores hash en un solo envío de ApiOperation.

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, no tener cambios, estar modificado, o no existir más en el repositorio de código fuente. Recupera cada elemento que sea nuevo o esté modificado para indexarlo. Quita los elementos del índice que ya no existan 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 se modificó (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 el RepositoryDoc.

Nota: La plantilla ListingConnector no admite que se muestre null en el método getDoc(). Si se muestra null, se generará un valor NullPointerException.

Controla los elementos borrados

En el siguiente fragmento de código, se 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 documentID no se encuentra en documents, muestra APIOperations.deleteItem(resourceName) para borrar el elemento del índice.

Controla elementos no modificados

En el siguiente fragmento de código, se 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 su estado, además de otros metadatos que pueden indicar un cambio. En el ejemplo, se usa el hash de metadatos para determinar si el elemento se modificó.

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

Establece los permisos para un elemento

El repositorio usa una Lista de control de acceso (LCA) para identificar a 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 esta LCA en la fuente de datos para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de búsqueda. Como tal, 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 a él.

El SDK de conector de contenido 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 de cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si la LCA del repositorio usa conceptos como la herencia de la LCA, modelarla puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta la sección sobre las LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search admite LCA de dominio único. No es compatible con LCA de dominio cruzado. Fundamentalmente, usarás la clase Acl.Builder para establecer el acceso a cada elemento mediante una LCA. En el siguiente fragmento de código, tomado de la muestra de recorrido completo, se permite a todos los usuarios o “principales” (getCustomerPrincipal()) ser “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();

Deberás comprender las LCA a fin de modelarlas de manera adecuada para la fuente de datos. Por ejemplo, podrías indexar archivos dentro de un sistema de archivos que use algún tipo de modelo de herencia mediante el que las carpetas secundarias hereden permisos de las carpetas superiores. Para modelar la herencia de LCA, se requiere información adicional incluida en la página sobre 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 como mínimo un ID de string ú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 mediante 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();

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 este modo 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 este modo para la indexación de actualizaciones y cambios en el repositorio. Si no se especifica, el modo de solicitud predeterminado es SYNCHRONOUS.

Pasos siguientes

Aquí hay algunos pasos que puedes seguir:

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

La cola de indexación de Cloud Search se usa a fin de conservar ID y valores hash opcionales para cada elemento en el repositorio. Un conector de recorrido de grafo 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 el contenido en ellas para determinar el estado de elementos, por ejemplo, si un elemento se borró del repositorio. Para obtener más información sobre la cola de indexación de la Búsqueda de Google, consulta la sección Cola de indexación de Google Cloud Search.

Durante la indexación, el contenido del elemento se recupera del repositorio de datos y cualquier ID secundario del elemento se envía a la cola. El conector continúa con el procesamiento recursivo de los ID superiores y secundarios hasta que se controlan todos los elementos.

En esta sección de los documentos, se 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 y, luego, 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. El ListingConnector acepta un objeto Repository que contiene los métodos que implementarás.

En el siguiente fragmento, se muestra cómo crear una instancia de ListingConnector y del 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() del conector llame a Application.build. El método initConfig() realiza las siguientes acciones:

  1. Llama al método Configuation.isInitialized() para garantizar que Configuration no se inicializó.
  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:

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

  • getIds(): a fin de recuperar los ID y los valores hash para todos los registros en el repositorio, anula el método getIds().

  • 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 defina tu configuración) para recuperar elementos modificados y, luego, indexarlos.

  • close() (opcional): si necesitas 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 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. Usarás el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, de FullTraversalSample, se muestra cómo recuperar un único 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 a fin de 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.

Luego 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 ID de los elementos y los valores hash de su contenido asociado del repositorio. Los ID y los pares de valores hash se empaquetan en una solicitud de operación push a la cola de indexación de Cloud Search. Por lo general, los ID superiores o raíz se envían primero, luego los ID secundarios, hasta que se procesa 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 de 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() muestra un CheckpointCloseableIterable, que es una iteración de objetos ApiOperation. Cada objeto representa una solicitud a la API realizada en un RepositoryDoc, como el envío de 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 cómo 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 ID y los valores hash en un solo envío de ApiOperation.

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, no tener cambios, estar modificado, o no existir más en el repositorio de código fuente. Recupera cada elemento que sea nuevo o esté modificado para indexarlo. Quita los elementos del índice que ya no existan en el repositorio de código fuente.

El método getDoc() acepta un elemento de la cola de indexación de la Búsqueda de Google. 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. Si 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 el RepositoryDoc.

Controla los elementos borrados

En el siguiente fragmento de código, se 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);

Establece los permisos para un elemento

El repositorio usa una Lista de control de acceso (LCA) para identificar a 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 esta LCA en la fuente de datos para garantizar que solo aquellos usuarios con acceso a un elemento puedan verlo en un resultado de búsqueda. Como tal, 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 a él.

El SDK de conector de contenido 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 de cada elemento en tu repositorio y crear una LCA correspondiente para Google Cloud Search cuando indexes un elemento. Si la LCA del repositorio usa conceptos como la herencia de la LCA, modelarla puede ser complicado. Para obtener más información sobre las LCA de Google Cloud Search, consulta la sección sobre las LCA de Google Cloud Search.

Nota: La API de indexación de Cloud Search admite LCA de dominio único. No es compatible con LCA de dominio cruzado. Fundamentalmente, usarás la clase Acl.Builder para establecer el acceso a cada elemento mediante una LCA. En el siguiente fragmento de código, tomado de la muestra de recorrido completo, se permite a todos los usuarios o “principales” (getCustomerPrincipal()) ser “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();

Deberás comprender las LCA a fin de modelarlas de manera adecuada para la fuente de datos. Por ejemplo, podrías indexar archivos dentro de un sistema de archivos que use algún tipo de modelo de herencia mediante el que las carpetas secundarias hereden permisos de las carpetas superiores. Para modelar la herencia de LCA, se requiere información adicional incluida en la página sobre 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 como mínimo un ID de string ú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 mediante 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 este modo 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 este modo 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

En el siguiente fragmento de código, se muestra cómo incluir los ID secundarios en la cola a fin de procesarlos, para el elemento superior que se encuentra en procesamiento. Estos ID se procesan después de que se indexa el elemento superior.

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

Pasos siguientes

Aquí hay algunos pasos que puedes seguir:

Crea un conector de contenido con la API de REST

En las siguientes secciones, se explica 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 desviar contenido de 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. A continuación, se describen tres estrategias de recorrido comunes:

Estrategia de recorrido completo

Con una estrategia de recorrido completo, se analiza todo el repositorio y, luego, se indexa a ciegas cada elemento. Esta estrategia se suele usar 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 que son, en su mayoría, 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

Con una estrategia de recorrido de lista, se analiza todo el repositorio, incluidos los nodos secundarios, y se determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos que sean nuevos o que se hayan actualizado desde la última indexación. Esta estrategia se suele usar 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, tienes datos no jerárquicos y trabajas con conjuntos de datos muy grandes.

Recorrido de grafos

Con una estrategia de recorrido de grafos, se analiza todo el nodo superior y se determina el estado de cada elemento. Luego, el conector realiza una segunda pasada y solo indexa elementos en el nodo raíz que sean nuevos o que se hayan actualizado desde la última indexación. Por último, el conector pasa cualquier ID secundario y, luego, indexa elementos en los nodos secundarios que sean nuevos o se hayan actualizado. El conector continúa de manera recursiva a través de todos los nodos secundarios hasta que se abordan todos los elementos. Por lo general, este recorrido se usa para los repositorios jerárquicos en los que no es práctico hacer una lista de todos los ID.

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

Implementa tu estrategia de recorrido y los elementos de índice

Cada elemento indexable para Google 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. Mediante 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. Mediante media.upload, a fin de subir archivos multimedia para indexar (opcional).

  3. Mediante items.index, para indexar el elemento. Por ejemplo, si tu esquema usara 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. Mediante llamadas a items.get para verificar que se indexó un elemento (opcional).

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

Maneja cambios en el repositorio

De forma periódica, puedes reunir y, también, indexar cada elemento de un repositorio para realizar una indexación completa. Si bien la indexación completa es efectiva para garantizar que tu índice esté actualizado, 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 se modificaron. Puedes usar las solicitudes items.push a fin de enviar elementos a la cola para consultarlos y actualizarlos más tarde. Para obtener más información sobre las colas de indexación de Google Cloud, consulta Cola de indexación de Google Cloud.

Para obtener más información sobre la API de REST de Cloud Search, consulta esta página sobre la API de Cloud Search.