Crea y administra el índice de RUM

En este documento, se muestra cómo crear la extensión de RUM y los índices para optimizar la búsqueda en el texto completo en AlloyDB para PostgreSQL. Se proporcionan ejemplos para casos de uso comunes, como la clasificación, la búsqueda de frases y la clasificación por marca de tiempo.

Antes de comenzar

Para crear la extensión de RUM, debes tener el alloydbsuperuser rol de base de datos.

El rol de IAM de AlloyDB Admin (roles/alloydb.admin) otorga control total sobre los recursos de AlloyDB, pero no otorga el rol de base de datos alloydbsuperuser. Para crear la extensión, un administrador debe otorgarte de forma explícita el rol de base de datos alloydbsuperuser.

Para obtener más información sobre cómo otorgar roles, consulta Agrega un usuario o una cuenta de servicio de IAM a un clúster.

Crea la extensión de RUM

Debes crear la extensión de RUM una vez por base de datos.

  1. Conéctate a tu base de datos de AlloyDB con psql o con otro cliente. Para obtener más información, consulta Conéctate a una instancia de clúster instance.
  2. Ejecuta el siguiente comando de SQL para crear la extensión:

    CREATE EXTENSION IF NOT EXISTS rum;
    

Crea un índice de RUM

Para optimizar las consultas de búsqueda en el texto completo, crea un índice de RUM en tus datos. RUM ofrece varias clases de operadores para diferentes casos de uso.

Tipos de clases de operadores de RUM

En la siguiente tabla, se resumen las diferentes clases de operadores de RUM y sus casos de uso principales.

Clase de operador Caso de uso principal Limitaciones
rum_tsvector_ops Búsqueda en el texto completo estándar con clasificación y búsqueda de frases N/A
rum_tsvector_hash_ops Índice más pequeño y actualizaciones más rápidas para la búsqueda en el texto completo No admite la búsqueda de prefijos
rum_tsvector_addon_ops Búsqueda en el texto completo ordenada por otra columna N/A
rum_anyarray_ops Búsqueda dentro de columnas de array N/A
rum_<TYPE>_ops Indexación de tipos escalares para consultas basadas en la distancia N/A
rum_tsvector_hash_addon_ops Búsqueda en el texto completo basada en hash ordenada por otra columna No admite la coincidencia de prefijos
rum_tsquery_ops Indexación de valores tsquery almacenados para la búsqueda inversa N/A
rum_anyarray_addon_ops Búsqueda de array ordenada por otra columna N/A

Usa la clase de operador rum_tsvector_ops para la búsqueda de texto estándar que requiere capacidades de clasificación rápida y búsqueda de frases. Esta clase de operador almacena la posición de cada lexema en el índice. En el siguiente ejemplo, se crea una tabla llamada documents con una columna content.

  1. Crea una tabla llamada documents:

    CREATE TABLE documents (
      id SERIAL PRIMARY KEY,
      title TEXT NOT NULL,
      content TEXT NOT NULL,
      published_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
    );
    
  2. Propaga la tabla documents con datos de muestra:

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    
  3. Agrega una columna tsvector generada a tu tabla. Esta columna almacena automáticamente el texto procesado y mejora el rendimiento de las consultas:

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    
  4. Crea el índice de RUM en la nueva columna search_vector:

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    
  5. Consulta la tabla con el índice. El operador <=> calcula la puntuación de relevancia o la distancia entre el documento y la consulta directamente desde el índice, lo que permite una clasificación rápida:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'search <-> engine')
    ORDER BY search_vector <=> to_tsquery('english', 'search <-> engine');
    
  6. Propaga la tabla documents con más datos:

    INSERT INTO documents (title, content) VALUES ('Title1', 'English is my primary language.');
    INSERT INTO documents (title, content) VALUES ('Title2', 'Google has a great engineering culture');
    
  7. Ejecuta una consulta de búsqueda de prefijos. Esto encuentra documentos que contienen palabras que comienzan con eng, como engineer o english:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'eng:*');
    

Usa la clase de operador rum_tsvector_hash_ops para reducir el tamaño del índice y mejorar las velocidades de actualización. Esta clase almacena un hash de cada lexema en lugar del lexema completo. Este enfoque da como resultado un índice más pequeño, pero no admite la búsqueda de prefijos. En el siguiente ejemplo, se supone que tienes una tabla llamada documents con una columna search_vector.

  1. Crea el índice de RUM con la clase de operador hash:

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    
  2. Propaga la tabla documents con más datos:

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    
  3. Ejecuta una consulta de coincidencia estándar:

    SELECT * FROM documents WHERE search_vector @@ to_tsquery('english', 'fast & efficient');
    
    

Índice para la búsqueda ordenada por marca de tiempo

Usa la clase de operador rum_tsvector_addon_ops para optimizar las consultas que filtran por texto y ordenan por otro campo, como una marca de tiempo. Este patrón almacena el valor del campo adicional directamente en el índice, lo que evita una operación de ordenamiento lenta después de la búsqueda. En el siguiente ejemplo, se supone que tienes una tabla llamada documents con una columna search_vector y una columna published_at.

  1. Crea un índice que incluya la marca de tiempo published_at:

    CREATE INDEX idx_docs_rum_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    
  2. Ejecuta una consulta que encuentre documentos que contengan la palabra engine y los ordene por fecha de publicación. El índice controla la búsqueda y el ordenamiento de manera eficiente:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

Usa la clase de operador rum_anyarray_ops para indexar columnas de array, como una lista de etiquetas. Esto te permite consultar de manera eficiente los arrays que se superponen (&&), contienen (@>) o están contenidos por (<@) otros arrays. En el siguiente ejemplo, se agrega una columna tags a la tabla documents.

  1. Agrega una columna tags y propágala con datos:

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    
  2. Crea el índice de RUM en una columna TEXT[] llamada tags:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. Ejecuta una consulta para encontrar documentos que tengan ai o ml en sus etiquetas:

    SELECT * FROM documents WHERE tags && '{"ai", "ml"}';
    

Índice para tipos escalares

Usa las clases de operador rum_<TYPE>_ops para indexar columnas que contienen valores continuos , como números enteros, marcas de tiempo o números de punto flotante. Estas clases de operador te permiten usar el operador <=> para calcular de manera eficiente la distancia entre los valores. En el siguiente ejemplo, se supone que tienes una tabla llamada documents.

  1. Agrega una columna de números enteros genérica, como rating, a la tabla documents:

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    
  2. Crea un índice de RUM en la columna rating:

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    
  3. Ejecuta una consulta para encontrar documentos con una rating más cercana al valor 5:

    SELECT title, rating
    FROM documents
    ORDER BY rating <=> 5;
    

Índice para la búsqueda de hash optimizada ordenada por marca de tiempo

Usa la clase de operador rum_tsvector_hash_addon_ops para combinar los beneficios de un índice hash con las capacidades de ordenamiento de un índice de complemento. Esta clase almacena un hash de cada lexema junto con el valor de una columna adicional. Esta configuración admite el ordenamiento eficiente por la columna adicional, pero no admite la coincidencia de prefijos. En el siguiente ejemplo, se supone que tienes una tabla llamada documents con una columna search_vector y una columna de marca de tiempo published_at.

  1. Crea un índice de RUM que use la clase de operador hash y que incluya la marca de tiempo published_at:

    CREATE INDEX idx_docs_rum_hash_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_hash_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    
  2. Ejecuta una consulta que encuentre documentos que contengan engine y los ordene por fecha de publicación:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

Índice para consultas almacenadas

Usa la clase de operador rum_tsquery_ops para indexar valores tsquery. Esto te permite realizar una "búsqueda inversa", que identifica qué consultas almacenadas coinciden con un documento de entrada determinado. En el siguiente ejemplo, se crea una tabla llamada queries.

  1. Crea una tabla para almacenar consultas:

    CREATE TABLE queries (
    query_text tsquery
    );
    INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));
    
  2. Crea un índice de RUM en la columna query_text:

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    
  3. Ejecuta una consulta para encontrar consultas almacenadas que coincidan con un documento:

    SELECT *
    FROM queries
    WHERE to_tsvector('english', 'AlloyDB is fast') @@ query_text;
    

Índice para la búsqueda de array ordenada por marca de tiempo

Usa la clase de operador rum_anyarray_addon_ops para indexar columnas de array junto con una columna adicional para el ordenamiento. En el siguiente ejemplo, se supone que tienes una tabla llamada documents con una columna tags y una columna de marca de tiempo published_at.

  1. Crea un índice de RUM en la columna tags que incluya la marca de tiempo published_at:

    CREATE INDEX idx_tags_rum_timestamp
    ON documents
    USING rum (tags rum_anyarray_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'tags');
    
  2. Ejecuta una consulta para encontrar documentos con la etiqueta ai, ordenados por fecha de publicación:

    SELECT title, published_at
    FROM documents
    WHERE tags @> '{"ai"}'
    ORDER BY published_at DESC;
    

¿Qué sigue?