Classificare i risultati di ricerca

Questa pagina descrive come classificare i risultati di ricerca per le ricerche a testo intero in Spanner.

Spanner supporta il calcolo di un punteggio di attualità, che fornisce un elemento di base per la creazione di funzioni di ranking sofisticate. Questi punteggi calcolano la pertinenza di un risultato rispetto a una query, in base alla frequenza dei termini della query e ad altre opzioni personalizzabili.

L'esempio seguente mostra come eseguire una ricerca con ranking utilizzando la funzione SCORE:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC

PostgreSQL

Questo esempio utilizza spanner.search con spanner.score.

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC

Assegna un punteggio ai termini di query con la funzione SCORE

La funzione SCORE calcola un punteggio per ogni termine della query e poi combina i punteggi. Il punteggio per termine si basa approssimativamente sulla frequenza del termine-frequenza inversa del documento (TF/IDF). Il punteggio è un componente dell'ordinamento finale di un record. La query lo combina con altri indicatori, come la novità, che modula il punteggio di attualità.

Nell'implementazione attuale, la parte IDF di TF/IDF è disponibile solo quando viene utilizzato enhance_query=>true. Calcola la frequenza relativa delle parole in base al corpus web completo utilizzato dalla Ricerca Google, anziché a un indice della Ricerca specifico. Se il miglioramento rquery non è abilitato, l'assegnazione del punteggio utilizza solo il componente della frequenza dei termini (TF), ovvero il termine IDF è impostato su 1.

La funzione SCORE restituisce valori che fungono da punteggi di pertinenza che Spanner utilizza per stabilire un ordinamento. Non hanno un significato autonomo. Più alto è il punteggio, migliore è la corrispondenza con la query.

In genere, argomenti come query e enhance_query sono gli stessi per entrambe le funzioni SEARCH e SCORE per garantire la coerenza nel recupero e nel ranking.

Il modo consigliato per farlo è utilizzare questi argomenti con i parametri di query anziché i valori letterali stringa e specificare gli stessi parametri di ricerca nelle funzioni SEARCH e SCORE.

Assegna un punteggio a più colonne

Spanner utilizza la funzione SCORE per assegnare un punteggio a ogni campo singolarmente. La query combina poi questi singoli punteggi. Un modo comune per farlo è sommare i singoli punteggi e poi aumentarli in base ai pesi dei campi forniti dall'utente (che vengono forniti utilizzando i parametri di query SQL).

Ad esempio, la seguente query combina l'output di due funzioni SCORE:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) OR SEARCH(Studio_Tokens, @p2)
ORDER BY SCORE(Title_Tokens, @p1) * @titleweight + SCORE(Studio_Tokens, @p2) * @studioweight
LIMIT 25

PostgreSQL

Questo esempio utilizza parametri di ricerca $1 e $2, che sono associati rispettivamente a "fifth symphony" e "blue note".

SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) OR spanner.search(studio_tokens, $2)
ORDER BY spanner.score(title_tokens, $1) * $titleweight
        + spanner.score(studio_tokens, $2) * $studioweight
LIMIT 25

L'esempio seguente aggiunge due parametri di boost:

  • La novità (FreshnessBoost) aumenta il punteggio con (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
  • La popolarità(PopularityBoost) aumenta il punteggio moltiplicandolo per il fattore (1 + IF(HasGrammy, @grammyweight, 0).

Per una maggiore leggibilità, la query utilizza l'operatore WITH.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) OR SEARCH(Studio_Tokens, @p2)
ORDER BY WITH(
  TitleScore AS SCORE(Title_Tokens, @p1) * @titleweight,
  StudioScore AS SCORE(Studio_Tokens, @p2) * @studioweight,
  DaysOld AS (UNIX_MICROS(CURRENT_TIMESTAMP()) - ReleaseTimestamp) / 8.64e+10,
  FreshnessBoost AS (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30),
  PopularityBoost AS (1 + IF(HasGrammy, @grammyweight, 0)),
  (TitleScore + StudioScore) * FreshnessBoost * PopularityBoost)
LIMIT 25

PostgreSQL

Questo esempio utilizza parametri di ricerca $1, $2, $3, $4, $5 e $6, che sono associati ai valori specificati rispettivamente per titlequery, studioquery, titleweight, studioweight, grammyweight e freshnessweight.

SELECT albumid
FROM
  (
    SELECT
      albumid,
      spanner.score(title_tokens, $1) * $3 AS titlescore,
      spanner.score(studio_tokens, $2) * $4 AS studioscore,
      (extract(epoch FROM current_timestamp) * 10e+6 - releasetimestamp) / 8.64e+10 AS daysold,
      (1 + CASE WHEN hasgrammy THEN $5 ELSE 0 END) AS popularityboost
    FROM albums
    WHERE spanner.search(title_tokens, $1) OR spanner.search(studio_tokens, $2)
  ) AS subquery
ORDER BY (subquery.TitleScore + subquery.studioscore)
  * (1 + $6 * greatest(0, 30 - subquery.daysold) / 30) * subquery.popularityboost
LIMIT 25

TOKENLIST_CONCAT può essere utilizzato anche sia nella ricerca che nell'assegnazione del punteggio per semplificare le query, se appropriato.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
ORDER BY SCORE(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
LIMIT 25

PostgreSQL

Questo esempio utilizza spanner.tokenlist_concat. Il parametro di query $1 è associato a "blue note".

SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
ORDER BY spanner.score(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
LIMIT 25

Corrispondenze dell'ordine delle query di boost

Spanner applica un boost moltiplicativo all'output della funzione SCORE per i valori che contengono i termini di query nello stesso ordine in cui vengono visualizzati nella query. Esistono due versioni di questo boost: corrispondenza parziale e corrispondenza esatta. Un boost di corrispondenza parziale viene applicato quando:

  1. TOKENLIST contiene tutti i termini originali della query.
  2. I token sono adiacenti l'uno all'altro e nello stesso ordine in cui vengono visualizzati nella query.

Esistono alcune regole speciali per congiunzioni, negazioni e frasi:

  • Una query con una negazione non può ricevere un boost di corrispondenza parziale.
  • Una query con una congiunzione riceve un boost se parte della congiunzione appare nelle posizioni appropriate.
  • Una query con una frase riceve un boost se la frase appare nel TOKENLIST e il termine a sinistra della frase nella query appare a sinistra della frase nel TOKENLIST, e lo stesso vale per il termine a destra della frase.

Spanner applica un boost di corrispondenza esatta quando tutte le regole precedenti sono vere e il primo e l'ultimo token della query sono il primo e l'ultimo token del documento.

Documento di esempio: Bridge Over Troubled Water

Query Boost applicato
Bridge Troubled nessun boost
Ponte su un altro corpo d'acqua nessun boost
Bridge (Over OR Troubled) Water nessun boost
Bridge Over boost parziale
Bridge Over (Troubled OR Water) boost parziale
Bridge Over Troubled Water boost esatto
Bridge "Over Troubled" Water boost esatto
Bridge ("Over Troubled" OR missingterm) Water boost esatto

Versioni dello scorer

L'algoritmo di punteggio viene aggiornato periodicamente. Ogni release raggruppa un insieme di miglioramenti dell'algoritmo di punteggio. Per un elenco dettagliato delle differenze tra le versioni, consulta Versioni di Scorer.

Puoi impostare la versione predefinita dello scorer per il tuo database o specificare una versione per una query specifica.

Se non specifichi una versione dello scorer per il database o la query, la versione predefinita dello scorer viene aggiornata automaticamente quando viene rilasciata una versione successiva.

Se impagini i risultati di ricerca classificati, le modifiche alla versione dello scorer possono causare righe saltate o ripetute nelle pagine. Per saperne di più, consulta Impagina i risultati di ricerca classificati.

Imposta la versione predefinita dello scorer del database

Puoi impostare la versione predefinita dell'algoritmo di punteggio per il tuo database. Questa opzione determina quale versione dell'algoritmo di punteggio viene utilizzata da Spanner quando la funzione SCORE viene chiamata senza un'opzione di punteggio version esplicita.

GoogleSQL

Imposta l'opzione di database score_version:

ALTER DATABASE database_name SET OPTIONS (score_version = 2)

PostgreSQL

Imposta l'opzione di database spanner.score_version:

ALTER DATABASE database_name SET "spanner.score_version" = 2

I valori validi per l'opzione del database sono 1 o 2. Se il parametro version è presente in una richiesta, esegue l'override della versione predefinita del database.

Esegui l'override della versione dello scorer per query

Puoi eseguire l'override della versione predefinita dello scorer per una query specifica utilizzando il parametro version nell'argomento options della funzione SCORE. Se una query definisce una versione dello scorer, questa sostituisce la versione predefinita del database.

L'esempio seguente esegue l'override della versione predefinita dello scorer specificando version nel parametro options:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, @query)
ORDER BY SCORE(
  AlbumTitle_Tokens,
  @query,
  options=>JSON '{"version": 2}'
) DESC

PostgreSQL

Questo esempio utilizza il parametro di query $1, che è associato alla stringa di query.

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, $1)
ORDER BY spanner.score(
  albumtitle_tokens,
  $1,
  options => '{"version": 2}'::jsonb
) DESC

Limita la profondità di recupero

Gli indici della Ricerca spesso contengono milioni di documenti. Per le query in cui i predicati hanno una bassa selettività, non è pratico classificare tutti i risultati. Le query di punteggio di solito hanno due limiti:

  1. Limite di profondità di recupero: il numero massimo di righe per cui calcolare il punteggio.
  2. Limite di dimensioni del set di risultati: il numero massimo di righe che la query deve restituire (in genere la dimensione della pagina).

Le query possono limitare la profondità di recupero con sottoquery SQL:

GoogleSQL

SELECT AlbumId
FROM
  (
    SELECT AlbumId, SCORE(Title_Tokens, @p1) AS score
    FROM Albums
    WHERE SEARCH(Title_Tokens, @p1)
    ORDER BY ReleaseTimestamp DESC
    LIMIT @retrieval_limit
  )
ORDER BY score DESC
LIMIT @page_size

PostgreSQL

Questo esempio utilizza parametri di ricerca $1, $2 e $3, che sono associati ai valori specificati rispettivamente per title_query, retrieval_limit e page_size.

SELECT albumid
FROM
  (
    SELECT albumid, spanner.score(title_tokens, $1) AS score
    FROM albums
    WHERE spanner.search(title_tokens, $1)
    ORDER BY releasetimestamp DESC
    LIMIT $2
  ) AS subquery
ORDER BY score DESC
LIMIT $3

Questo approccio funziona particolarmente bene se Spanner utilizza l'indicatore di ranking più importante per ordinare l'indice.

Passaggi successivi