Questa pagina descrive come classificare i risultati della ricerca per le ricerche full-text in Spanner.
Spanner supporta il calcolo di un punteggio di topicalità, che fornisce un componente di base per la creazione di funzioni di classificazione sofisticate. Questi punteggi calcolano la pertinenza di un risultato per una query, in base alla frequenza dei termini di query e ad altre opzioni personalizzabili.
L'esempio seguente mostra come eseguire una ricerca classificata utilizzando la
SCORE
funzione:
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
Assegnare un punteggio ai termini di query con la funzione SCORE
La SCORE
funzione calcola un punteggio per ogni termine di query e poi combina i punteggi. Il
punteggio per termine si basa approssimativamente sulla frequenza dei termini-frequenza inversa dei documenti
(TF/IDF). Il punteggio è un componente dell'ordinamento finale di un record. La query lo combina con altri segnali, come la novità che modula il punteggio di topicalità.
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 di ricerca specifico. Se il miglioramento della query non è attivato, l'assegnazione dei punteggi utilizza solo il componente di frequenza dei termini (TF), ovvero il termine IDF è impostato su 1.
La funzione SCORE restituisce valori che fungono da punteggi di pertinenza utilizzati da Spanner per stabilire un ordinamento. Non hanno un significato autonomo. Più alto è il punteggio, migliore è la corrispondenza con la query.
In genere, gli argomenti come query e enhance_query sono gli stessi per le funzioni
SEARCH e SCORE per garantire la coerenza nel recupero e nella classificazione.
Il modo consigliato per farlo è utilizzare questi argomenti con
parametri di query
anziché con i valori letterali stringa e specificare gli stessi parametri di ricerca nelle funzioni
SEARCH e SCORE.
Assegnare un punteggio a più colonne
Spanner utilizza la funzione SCORE per assegnare un punteggio a ogni campo singolarmente. La query combina quindi questi punteggi individuali. Un modo comune per farlo è sommare i punteggi individuali e poi aumentarli in base ai pesi dei campi forniti dall'utente (che vengono forniti utilizzando i parametri di query SQL).
Ad esempio, la query seguente 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 rispettivamente ai valori specificati 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 nella ricerca e nell'assegnazione dei punteggi 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
Aumentare le corrispondenze dell'ordine delle query
Spanner applica un boost moltiplicativo all'output della funzione SCORE per i valori che contengono i termini di query nello stesso ordine in cui appaiono nella query. Esistono due versioni di questo boost: corrispondenza parziale e corrispondenza esatta. Viene applicato un boost di corrispondenza parziale quando:
- Il
TOKENLISTcontiene tutti i termini originali della query. - I token sono adiacenti l'uno all'altro e nello stesso ordine in cui appaiono nella query.
Esistono 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 una parte della congiunzione appare nelle posizioni appropriate.
- Una query con una frase riceve un boost se la frase appare nel
TOKENLIST, il termine a sinistra della frase nella query appare a sinistra della frase nelTOKENLISTe 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 nella query sono il primo e l'ultimo token nel documento.
Documento di esempio: Bridge Over Troubled Water
| Query | Boost applicato |
|---|---|
| Bridge Troubled | nessun boost |
| Bridge Over - other water | 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 di Scorer
L'algoritmo di Scorer viene aggiornato periodicamente. Ogni release include un insieme di miglioramenti dell'algoritmo di assegnazione dei punteggi. Per un elenco dettagliato delle differenze tra le versioni, consulta Versioni di Scorer.
Puoi impostare la versione predefinita di Scorer per il tuo database oppure specificare una versione per una query specifica.
Impostare la versione predefinita di Scorer del database
Puoi impostare la versione predefinita dell'algoritmo di Scorer per il tuo database. Questa opzione determina la versione dell'algoritmo di assegnazione dei punteggi utilizzata da Spanner quando viene chiamata la funzione SCORE senza un'opzione di punteggio version esplicita.
GoogleSQL
Imposta l'opzione del database score_version:
ALTER DATABASE database_name SET OPTIONS (score_version = 2)
PostgreSQL
Imposta l'opzione del 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, sostituisce la versione predefinita del database.
Sostituire la versione di Scorer per query
Puoi sostituire la versione predefinita di Scorer per una query specifica utilizzando il parametro version nell'argomento options della funzione SCORE. Se una query definisce una versione di Scorer, sostituisce la versione predefinita del database.
L'esempio seguente sostituisce la versione predefinita di 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
Limitare la profondità di recupero
Gli indici di 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 assegnazione dei punteggi in genere hanno due limiti:
- Limite di profondità di recupero: il numero massimo di righe a cui assegnare un punteggio.
- Limite di dimensioni del set di risultati: il numero massimo di righe che la query deve restituire (in genere le dimensioni della pagina).
Le query possono limitare la profondità di recupero con le 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 rispettivamente ai valori specificati 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 funziona particolarmente bene se Spanner utilizza l'indicatore di ranking più importante per ordinare l'indice.
Passaggi successivi
- Scopri di più sulle query di ricerca full-text.
- Scopri come eseguire una ricerca di sottostringhe.
- Scopri come impaginare i risultati di ricerca.
- Scopri come combinare query full-text e non di testo.
- Scopri come eseguire ricerche in più colonne.