Créer et gérer un index RUM

Ce document explique comment créer l'extension RUM et des index pour optimiser la recherche en texte intégral dans AlloyDB pour PostgreSQL. Il fournit des exemples pour les cas d'utilisation courants, y compris le classement, la recherche d'expressions et le tri par code temporel.

Avant de commencer

Pour créer l'extension RUM, vous devez disposer du rôle alloydb_superuser. Pour en savoir plus sur l'attribution de rôles, consultez Ajouter un utilisateur ou un compte de service IAM à un cluster.

Créer l'extension RUM

Vous devez créer l'extension RUM une fois par base de données.

  1. Connectez-vous à votre base de données AlloyDB à l'aide de psql ou d'un autre client. Pour en savoir plus, consultez Se connecter à une instance de cluster.
  2. Exécutez la commande SQL suivante pour créer l'extension :

    CREATE EXTENSION IF NOT EXISTS rum;
    

Créer un index RUM

Pour optimiser les requêtes de recherche en texte intégral, créez un index RUM sur vos données. RUM propose plusieurs classes d'opérateurs pour différents cas d'utilisation.

Types de classes d'opérateurs RUM

Le tableau suivant récapitule les différentes classes d'opérateurs RUM et leurs principaux cas d'utilisation.

Classe d'opérateur Cas d'utilisation principal Limites
rum_tsvector_ops Recherche en texte intégral standard avec classement et recherche d'expressions. N/A
rum_tsvector_hash_ops Index plus petit et mises à jour plus rapides pour la recherche en texte intégral. La recherche par préfixe n'est pas disponible.
rum_tsvector_addon_ops Recherche en texte intégral triée par une autre colonne. N/A
rum_anyarray_ops Rechercher dans les colonnes de tableaux. N/A
rum_<TYPE>_ops Indexation des types scalaires pour les requêtes basées sur la distance. N/A
rum_tsvector_hash_addon_ops Recherche en texte intégral basée sur le hachage, triée par une autre colonne. Ne prend pas en charge la correspondance des préfixes.
rum_tsquery_ops Indexation des valeurs tsquery stockées pour la recherche inversée. N/A
rum_anyarray_addon_ops Recherche de tableau triée par une autre colonne. N/A

Utilisez la classe d'opérateur rum_tsvector_ops pour la recherche de texte standard qui nécessite des fonctionnalités de classement rapide et de recherche d'expressions. Cette classe d'opérateurs stocke la position de chaque lexème dans l'index. L'exemple suivant crée une table nommée documents avec une colonne content.

  1. Créez une table nommée 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. Remplissez la table documents avec des exemples de données :

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    
  3. Ajoutez une colonne tsvector générée à votre tableau. Cette colonne stocke automatiquement le texte traité et améliore les performances des requêtes :

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    
  4. Créez l'index RUM sur la nouvelle colonne search_vector :

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    
  5. Interrogez la table à l'aide de l'index. L'opérateur <=> calcule le score de pertinence, ou la distance, entre le document et la requête directement à partir de l'index, ce qui permet un tri rapide :

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'search <-> engine')
    ORDER BY search_vector <=> to_tsquery('english', 'search <-> engine');
    
  6. Remplissez la table documents avec d'autres données :

    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. Exécutez une requête de recherche par préfixe. Cette requête permet de trouver les documents contenant des mots commençant par eng, comme engineer ou english :

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

Utilisez la classe d'opérateur rum_tsvector_hash_ops pour réduire la taille de l'index et améliorer la vitesse de mise à jour. Cette classe stocke un hachage de chaque lexème au lieu du lexème complet. Cette approche permet d'obtenir un index plus petit, mais ne prend pas en charge la recherche par préfixe. L'exemple suivant suppose que vous disposez d'une table nommée documents avec une colonne search_vector.

  1. Créez l'index RUM à l'aide de la classe d'opérateur de hachage :

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    
  2. Remplissez la table documents avec d'autres données :

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    
  3. Exécutez une requête de correspondance standard :

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

Index pour la recherche trié par code temporel

Utilisez la classe d'opérateur rum_tsvector_addon_ops pour optimiser les requêtes qui filtrent par texte et trient par un autre champ, tel qu'un code temporel. Ce modèle stocke la valeur du champ supplémentaire directement dans l'index, ce qui évite une opération de tri lente après la recherche. L'exemple suivant suppose que vous disposez d'une table nommée documents avec une colonne search_vector et une colonne published_at.

  1. Créez un index qui inclut le code temporel 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. Exécutez une requête qui recherche les documents contenant le mot engine et les trie par date de publication. L'index gère efficacement la recherche et le tri :

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

Utilisez la classe d'opérateur rum_anyarray_ops pour indexer les colonnes de tableau, telles qu'une liste de tags. Cela vous permet d'interroger efficacement les tableaux qui se chevauchent (&&), contiennent (@>) ou sont contenus dans (<@) d'autres tableaux. L'exemple suivant ajoute une colonne tags à la table documents.

  1. Ajoutez une colonne tags et remplissez-la avec des données :

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    
  2. Créez l'index RUM sur une colonne TEXT[] nommée tags :

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. Exécutez une requête pour trouver les documents dont les tags contiennent ai ou ml :

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

Index pour les types scalaires

Utilisez les classes d'opérateurs rum_<TYPE>_ops pour indexer les colonnes contenant des valeurs continues, telles que des entiers, des codes temporels ou des nombres à virgule flottante. Ces classes d'opérateurs vous permettent d'utiliser l'opérateur <=> pour calculer efficacement la distance entre les valeurs. L'exemple suivant suppose que vous disposez d'une table nommée documents.

  1. Ajoutez une colonne d'entiers générique, telle que rating, à la table documents :

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    
  2. Créez un index RUM sur la colonne rating :

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    
  3. Exécutez une requête pour trouver les documents dont le rating est le plus proche de la valeur 5 :

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

Index pour la recherche de hachages optimisée, trié par code temporel

Utilisez la classe d'opérateur rum_tsvector_hash_addon_ops pour combiner les avantages d'un index de hachage avec les capacités de tri d'un index de complément. Cette classe stocke un hachage de chaque lexème ainsi que la valeur d'une colonne supplémentaire. Cette configuration permet un tri efficace par la colonne supplémentaire, mais pas la correspondance des préfixes. L'exemple suivant suppose que vous disposez d'une table nommée documents avec une colonne search_vector et une colonne d'horodatage published_at.

  1. Créez un index RUM qui utilise la classe d'opérateur de hachage et inclut le code temporel 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. Exécutez une requête qui recherche les documents contenant engine et les trie par date de publication :

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

Index pour les requêtes stockées

Utilisez la classe d'opérateur rum_tsquery_ops pour indexer les valeurs tsquery. Cela vous permet d'effectuer une "recherche inversée" pour identifier les requêtes stockées qui correspondent à un document d'entrée donné. L'exemple suivant crée une table nommée queries.

  1. Créez une table pour stocker les requêtes :

    CREATE TABLE queries (
    query_text tsquery
    );
    INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));
    
  2. Créez un index RUM sur la colonne query_text :

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    
  3. Exécutez une requête pour trouver les requêtes stockées qui correspondent à un document :

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

Index pour la recherche de tableaux triés par code temporel

Utilisez la classe d'opérateur rum_anyarray_addon_ops pour indexer les colonnes de tableau avec une colonne supplémentaire pour le tri. L'exemple suivant suppose que vous disposez d'une table nommée documents avec une colonne tags et une colonne d'horodatage published_at.

  1. Créez un index RUM sur la colonne tags qui inclut le code temporel 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. Exécutez une requête pour trouver les documents portant le tag ai, triés par date de publication :

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

Étapes suivantes