Criar e consultar um índice RUM

Os índices RUM no AlloyDB para PostgreSQL permitem acelerar as consultas de pesquisa de texto completo armazenando informações posicionais e de atributos junto com lexemas no índice. É possível ativar a extensão rum para criar índices RUM e otimizar a classificação de relevância, as pesquisas de frases e a classificação com base em carimbos de data/hora.

Antes de começar

Para criar a extensão RUM, é preciso ter o papel de banco de dados alloydbsuperuser.

O papel de administrador do AlloyDB (roles/alloydb.admin) do Identity and Access Management (IAM) concede controle total sobre os recursos do AlloyDB, mas não concede o papel de banco de dados alloydbsuperuser. Para criar a extensão, um administrador precisa conceder explicitamente a você o papel de banco de dados alloydbsuperuser.

Para mais informações sobre como conceder papéis, consulte Adicionar um usuário ou uma conta de serviço do IAM a um cluster.

Criar a extensão do RUM

É necessário criar a extensão RUM uma vez por banco de dados.

  1. Conecte-se ao banco de dados do AlloyDB usando psql ou outro cliente. Para mais informações, consulte Conectar-se a uma instância de cluster.
  2. Execute o seguinte comando SQL para criar a extensão:

    CREATE EXTENSION IF NOT EXISTS rum;
    

Criar um índice RUM

Para otimizar as consultas de pesquisa de texto completo, crie um índice RUM nos seus dados. O RUM oferece várias classes de operador para diferentes casos de uso.

Tipos de classes de operador RUM

A tabela a seguir resume as diferentes classes de operador de RUM e os principais casos de uso delas.

Classe de operador Caso de uso principal Limitações
rum_tsvector_ops Pesquisa de texto completo padrão com classificação e pesquisa de frases. N/A
rum_tsvector_hash_ops Índice menor e atualizações mais rápidas para pesquisa de texto completo. Não aceita pesquisa de prefixo.
rum_tsvector_addon_ops Pesquisa de texto completo classificada por outra coluna. N/A
rum_anyarray_ops Pesquisa em colunas de matriz. N/A
rum_<TYPE>_ops Indexação de tipos escalares para consultas baseadas em distância. N/A
rum_tsvector_hash_addon_ops Pesquisa de texto completo baseada em hash classificada por outra coluna. Não é compatível com correspondência de prefixo.
rum_tsquery_ops Indexação de valores tsquery armazenados para pesquisa reversa. N/A
rum_anyarray_addon_ops Pesquisa de matriz ordenada por outra coluna. N/A

Use a classe de operador rum_tsvector_ops para Text Search padrão que exige recursos rápidos de classificação e pesquisa de frases. Essa classe de operador armazena a posição de cada lexema no índice. O exemplo a seguir cria uma tabela chamada documents com uma coluna content.

  1. Crie uma tabela chamada 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. Preencha a tabela documents com dados de amostra:

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    
  3. Adicione uma coluna tsvector gerada à tabela. Essa coluna armazena automaticamente o texto processado e melhora o desempenho da consulta:

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    
  4. Crie o índice RUM na nova coluna search_vector:

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    
  5. Consulte a tabela usando o índice. O operador <=> calcula a pontuação de relevância ou a distância entre o documento e a consulta diretamente do índice, permitindo uma classificação 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. Preencha a tabela documents com mais dados:

    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. Execute uma consulta de pesquisa de prefixo. Isso encontra documentos que contêm palavras que começam com eng, como engineer ou english:

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

Use a classe de operador rum_tsvector_hash_ops para reduzir o tamanho do índice e melhorar as velocidades de atualização. Essa classe armazena um hash de cada lexema em vez do lexema completo. Essa abordagem resulta em um índice menor, mas não é compatível com a pesquisa de prefixo. O exemplo a seguir pressupõe que você tenha uma tabela chamada documents com uma coluna search_vector.

  1. Crie o índice RUM usando a classe de operador de hash:

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    
  2. Preencha a tabela documents com mais dados:

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    
  3. Execute uma consulta de correspondência padrão:

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

Índice para pesquisa classificado por carimbo de data/hora

Use a classe de operador rum_tsvector_addon_ops para otimizar consultas que filtram por texto e classificam por outro campo, como um carimbo de data/hora. Esse padrão armazena o valor do campo adicional diretamente no índice, o que evita uma operação de classificação lenta após a pesquisa. O exemplo a seguir pressupõe que você tenha uma tabela chamada documents com uma coluna search_vector e uma coluna published_at.

  1. Crie um índice que inclua o carimbo de data/hora 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. Execute uma consulta que encontre documentos que contenham a palavra engine e os classifique por data de publicação. O índice lida com a pesquisa e a classificação de maneira eficiente:

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

Use a classe de operador rum_anyarray_ops para indexar colunas de matriz, como uma lista de tags. Isso permite consultar com eficiência matrizes que se sobrepõem (&&), contêm (@>) ou são contidas por (<@) outras matrizes. O exemplo a seguir adiciona uma coluna tags à tabela documents.

  1. Adicione uma coluna tags e preencha-a com dados:

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    
  2. Crie o índice RUM em uma coluna TEXT[] chamada tags:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. Execute uma consulta para encontrar documentos que tenham ai ou ml nas tags:

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

Índice para tipos escalares

Use as classes de operador rum_<TYPE>_ops para indexar colunas que contêm valores contínuos, como números inteiros, carimbos de data/hora ou números de ponto flutuante. Essas classes de operador permitem usar o operador <=> para calcular com eficiência a distância entre os valores. No exemplo a seguir, pressupomos que você tenha uma tabela chamada documents.

  1. Adicione uma coluna de números inteiros genérica, como rating, à tabela documents:

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    
  2. Crie um índice RUM na coluna rating:

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    
  3. Execute uma consulta para encontrar documentos com um rating mais próximo do valor 5:

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

Índice para pesquisa de hash otimizada classificada por carimbo de data/hora

Use a classe de operador rum_tsvector_hash_addon_ops para combinar os benefícios de um índice de hash com os recursos de classificação de um índice de complemento. Essa classe armazena um hash de cada lexema com o valor de uma coluna extra. Essa configuração permite uma classificação eficiente pela coluna extra, mas não permite a correspondência de prefixo. O exemplo a seguir pressupõe que você tenha uma tabela chamada documents com uma coluna search_vector e uma coluna de carimbo de data/hora published_at.

  1. Crie um índice RUM que use a classe de operador de hash e inclua o carimbo de data/hora 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. Execute uma consulta que encontre documentos que contenham engine e os classifique por data de publicação:

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

Índice para consultas armazenadas

Use a classe de operador rum_tsquery_ops para indexar valores tsquery. Isso permite realizar uma "pesquisa reversa", identificando quais consultas armazenadas correspondem a um determinado documento de entrada. No exemplo a seguir, criamos uma tabela denominada queries.

  1. Crie uma tabela para armazenar consultas:

    CREATE TABLE queries (
    query_text tsquery
    );
    INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));
    
  2. Crie um índice RUM na coluna query_text:

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    
  3. Execute uma consulta para encontrar consultas armazenadas que correspondam a um documento:

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

Índice para pesquisa de matriz classificado por carimbo de data/hora

Use a classe de operador rum_anyarray_addon_ops para indexar colunas de matriz com uma coluna adicional para classificação. No exemplo a seguir, pressupomos que você tenha uma tabela chamada documents com uma coluna tags e uma coluna de carimbo de data/hora published_at.

  1. Crie um índice RUM na coluna tags que inclua o carimbo de data/hora 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. Execute uma consulta para encontrar documentos com a tag ai, classificados por data de publicação:

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

A seguir