Combinare query a testo intero e non di testo

Questa pagina descrive come eseguire una ricerca che mescola dati a testo intero e non di testo.

Gli indici di ricerca supportano le colonne di testo completo, a corrispondenza esatta, numeriche e JSON/JSONB. Puoi combinare condizioni di testo e non di testo nella clausola WHERE in modo simile alle query di ricerca con più colonne. Lo strumento di ottimizzazione delle query tenta di ottimizzare i predicati non di testo con un indice di ricerca. Se non è possibile, Spanner valuta la condizione per ogni riga che corrisponde all'indice di ricerca. Le colonne a cui viene fatto riferimento non almacenate nell'indice di ricerca vengono recuperate dalla tabella di base.

Considera l'esempio seguente:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  Title STRING(MAX),
  Rating FLOAT64,
  Genres ARRAY<STRING(MAX)>,
  Likes INT64,
  Cover BYTES(MAX),
  Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
  Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN,
  Genres_Tokens TOKENLIST AS (TOKEN(Genres)) HIDDEN
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex
ON Albums(Title_Tokens, Rating_Tokens, Genres_Tokens)
STORING (Likes);

PostgreSQL

Il supporto di PostgreSQL per Spanner presenta le seguenti limitazioni:

  • La funzione spanner.tokenize_number supporta solo il tipo bigint.
  • spanner.token non supporta la tokenizzazione degli array.
CREATE TABLE albums (
  albumid character varying NOT NULL,
  title character varying,
  rating bigint,
  genres character varying NOT NULL,
  likes bigint,
  cover bytea,
  title_tokens spanner.tokenlist AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
  rating_tokens spanner.tokenlist AS (spanner.tokenize_number(rating)) VIRTUAL HIDDEN,
  genres_tokens spanner.tokenlist AS (spanner.token(genres)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));

CREATE SEARCH INDEX albumsindex
ON albums(title_tokens, rating_tokens, genres_tokens)
INCLUDE (likes);

Il comportamento delle query su questa tabella è il seguente:

  • Rating e Genres sono inclusi nell'indice di ricerca. Spanner accelera le condizioni utilizzando elenchi di posting dell'indice di ricerca. ARRAY_INCLUDES_ANY, ARRAY_INCLUDES_ALL sono funzioni GoogleSQL e non sono supportate per il dialetto PostgreSQL.

    SELECT Album
    FROM Albums
    WHERE Rating > 4
      AND ARRAY_INCLUDES_ANY(Genres, ['jazz'])
    
  • La query può combinare connessioni, disgiunzioni e negazioni in qualsiasi modo, incluso il mix di predicati di testo completo e non di testo. Questa query è completamente accelerata dall'indice di ricerca.

    SELECT Album
    FROM Albums
    WHERE (SEARCH(Title_Tokens, 'car')
          OR Rating > 4)
      AND NOT ARRAY_INCLUDES_ANY(Genres, ['jazz'])
    
  • Likes è archiviato nell'indice, ma lo schema non richiede a Spanner di creare un indice di token per i relativi possibili valori. Pertanto, il predicato di testo completo su Title e il predicato non di testo su Rating vengono accelerati, ma non il predicato su Likes. In Spanner, la query recupera tutti i documenti con il termine "auto" in Title e una valutazione superiore a 4, quindi filtra i documenti che non hanno almeno 1000 Mi piace. Questa query utilizza molte risorse se quasi tutti gli album contengono il termine "auto" nel titolo e quasi tutti hanno una valutazione di 5, ma pochi album hanno 1000 Mi piace. In questi casi, l'indicizzazione di Likes in modo simile a Rating consente di risparmiare risorse.

    GoogleSQL

    SELECT Album
    FROM Albums
    WHERE SEARCH(Title_Tokens, 'car')
      AND Rating > 4
      AND Likes >= 1000
    

    PostgreSQL

    SELECT album
    FROM albums
    WHERE spanner.search(title_tokens, 'car')
      AND rating > 4
      AND likes >= 1000
    
  • Cover non è memorizzato nell'indice. La seguente query esegue un join posteriore tra AlbumsIndex e Albums per recuperare Cover per tutti gli album corrispondenti.

    GoogleSQL

    SELECT AlbumId, Cover
    FROM Albums
    WHERE SEARCH(Title_Tokens, 'car')
      AND Rating > 4
    

    PostgreSQL

    SELECT albumid, cover
    FROM albums
    WHERE spanner.search(title_tokens, 'car')
      AND rating > 4
    

Passaggi successivi