Auf dieser Seite wird beschrieben, wie Sie TOKENLIST
s entweder in einem Suchindex beim Einrichten Ihres Schemas oder in einer Suchanfrage bei einer Volltextsuche in Spanner zusammenführen.
TOKENLISTs in einem Suchindex kombinieren
Manchmal muss Ihre Anwendung in einzelnen Feldern suchen. In anderen Fällen muss die Anwendung in allen Feldern suchen. In einer Tabelle mit zwei Stringspalten kann Ihre Anwendung beispielsweise in beiden Spalten suchen, ohne zu unterscheiden, aus welcher Spalte die Übereinstimmungen stammen.
In Spanner gibt es zwei Möglichkeiten, dies zu erreichen:
- Wörter einzeln tokenisieren und die resultierenden
TOKENLIST
s zusammenführen (empfohlen). - Strings zusammenführen und das Ergebnis tokenisieren.
Beim zweiten Ansatz gibt es zwei Probleme:
- Wenn Sie
Title
oderStudio
einzeln indexieren möchten, wird derselbe Text nicht nur in einem kombiniertenTOKENLIST
indexiert, sondern auch zweimal tokenisiert. Dadurch werden für Transaktionen mehr Ressourcen benötigt. - Eine Wortgruppensuche umfasst beide Felder. Wenn
@p
beispielsweise auf"Blue Note"
festgelegt ist, wird eine Zeile mitTitle
=„Big Blue Note“ undStudio
=„Blue Note Studios“ gefunden.
Mit dem ersten Ansatz werden diese Probleme gelöst, da eine Wortgruppe nur mit einem Feld übereinstimmt und jedes Stringfeld nur einmal tokenisiert wird, wenn sowohl die einzelnen als auch die kombinierten TOKENLIST
s indexiert werden. Auch wenn jedes Stringfeld nur einmal tokenisiert wird, werden die resultierenden TOKENLIST
s separat im Index gespeichert.
Wörter separat tokenisieren und TOKENLIST
s zusammenführen
Im folgenden Beispiel werden die einzelnen Wörter tokenisiert und die TOKENLIST
s mit TOKENLIST_CONCAT
zusammengefügt:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
Combined_Tokens TOKENLIST AS (TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens])) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
PostgreSQL
In PostgreSQL wird spanner.tokenlist_concat
für die Koncatenate verwendet. Der Abfrageparameter $1
ist an „Hatel Kaliphorn“ gebunden.
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenlist_concat(ARRAY[spanner.tokenize_fulltext(title), spanner.tokenize_fulltext(studio)])) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
Beachten Sie, dass tokenlist_concat
nicht title_tokens
oder studio_tokens
, sondern spanner.tokenize_fulltext(title)
und spanner.tokenize_fulltext(studio)
aufruft. Das liegt daran, dass PostgreSQL keine Verweise auf generierte Spalten unterstützt, die sich in anderen generierten Spalten befinden. spanner.tokenlist_concat
muss Tokenisierungsfunktionen aufrufen und nicht direkt auf Tokenlistenspalten verweisen.
Die TOKENLIST
-Konkatenierung kann auch vollständig auf Abfrageseite implementiert werden.
Weitere Informationen finden Sie unter Abfrageseitige TOKENLIST
Verkettung.
TOKENLIST_CONCAT
wird sowohl für die Volltextsuche als auch für die Suche nach einem Teilstring unterstützt.
In Spanner können Sie keine Tokenisierungstypen wie TOKENIZE_FULLTEXT
und TOKENIZE_SUBSTRING
in einem einzigen TOKENLIST_CONCAT
-Aufruf mischen.
In GoogleSQL kann die Definition von TextTOKENLIST
-Spalten in nicht gespeicherten Spalten geändert werden, um zusätzliche Spalten hinzuzufügen. Das ist nützlich, wenn Sie TOKENLIST_CONCAT
eine zusätzliche Spalte hinzufügen möchten. Wenn Sie den Ausdruck der generierten Spalte ändern, werden vorhandene Zeilen im Index nicht aufgefüllt.
Strings zusammenführen und das Ergebnis tokenisieren
Im folgenden Beispiel werden Strings zusammengefügt und das Ergebnis tokenisiert:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Combined_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title || " " || Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Combined_Tokens);
SELECT AlbumId FROM Albums WHERE SEARCH(Combined_Tokens, @p);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
combined_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title || ' ' || studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(combined_tokens);
SELECT albumid FROM albums WHERE spanner.search(combined_tokens, $1);
Abfrageseitige TOKENLIST
-Konkatenierung
Die Indexierung der zusammengesetzten TOKENLIST
erhöht jedoch die Speicher- und Schreibkosten. Jedes Token wird jetzt zweimal auf dem Laufwerk gespeichert: einmal in einer Postingliste der ursprünglichen TOKENLIST
und einmal in einer Postingliste der kombinierten TOKENLIST
. Durch die abfrageseitige Konkatenierung von TOKENLIST
-Spalten werden diese Kosten vermieden, die Abfrage verbraucht jedoch mehr Rechenressourcen.
Wenn Sie mehrere TOKENLIST
-Werte verketten möchten, verwenden Sie die Funktion TOKENLIST_CONCAT
in der Abfrage SEARCH
. In diesem Abschnitt verwenden wir das folgende Beispielschema:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
Title STRING(MAX),
Studio STRING(MAX),
Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN,
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(Title_Tokens, Studio_Tokens);
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
title character varying,
studio character varying,
title_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
studio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(studio)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(title_tokens, studio_tokens);
Mit der folgenden Abfrage wird in den Spalten Title
und Studio
nach Zeilen gesucht, die die Tokens „blau“ und „Notiz“ enthalten. Dazu gehören Zeilen mit „blau“ und „Hinweis“ in der Spalte Title
, „blau“ und „Hinweis“ in der Spalte Studio
, „blau“ in der Spalte Title
und „Hinweis“ in der Spalte Studio
oder umgekehrt.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([AlbumTitle_Tokens, Studio_Tokens]), 'blue note')
PostgreSQL
In diesem Beispiel wird spanner.search
mit spanner.tokenlist_concat
verwendet.
SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[albumtitle_tokens, studio_tokens]), 'blue note')
Die Konkatenierung von TOKENLIST
auf Schreib- und Abfrageseite führt zu identischen Ergebnissen.
Die Entscheidung zwischen den beiden Optionen ist ein Kompromiss zwischen Speicher- und Abfragekosten.
Alternativ kann eine Anwendung in mehreren TOKENLIST
-Spalten suchen und OR
zusammen mit der Funktion SEARCH
verwenden:
GoogleSQL
SEARCH(AlbumTitle_Tokens, 'Blue Note') OR SEARCH(Studio_Tokens, 'Blue Note')
PostgreSQL
spanner.search(albumtitle_tokens, 'Blue Note') OR spanner.search(studio_tokens, 'Blue Note')
Dieser hat jedoch eine andere Semantik. Dies gilt nicht für Alben, bei denen AlbumTitle_Tokens
„blau“ und nicht „Notiz“ und Studio_Tokens
„Notiz“ und nicht „blau“ enthält.