TOKENLISTs kombinieren

Auf dieser Seite wird beschrieben, wie Sie TOKENLISTs 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:

  1. Wörter einzeln tokenisieren und die resultierenden TOKENLIST-Werte zusammenführen (empfohlen)
  2. Strings zusammenführen und das Ergebnis tokenisieren.

Beim zweiten Ansatz gibt es zwei Probleme:

  1. Wenn Sie Title oder Studio einzeln indexieren möchten, wird derselbe Text nicht nur in einem kombinierten TOKENLIST indexiert, sondern auch zweimal tokenisiert. Dadurch werden für Transaktionen mehr Ressourcen benötigt.
  2. Eine Wortgruppensuche umfasst beide Felder. Wenn @p beispielsweise auf "Blue Note" festgelegt ist, wird eine Zeile mit Title=„Big Blue Note“ und Studio=„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 indexiert werden. Auch wenn jedes Stringfeld nur einmal tokenisiert wird, werden die resultierenden TOKENLISTs separat im Index gespeichert.

Wörter einzeln tokenisieren und TOKENLIST-Werte verketten

Im folgenden Beispiel werden alle Wörter tokenisiert und die TOKENLIST-Werte zusammengefügt:

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);

Die TOKENLIST-Konkatenierung kann auch vollständig auf Abfrageseite implementiert werden. Weitere Informationen finden Sie unter Abfrageseitige TOKENLIST-Konkatenierung.

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.

Die Definition von TextTOKENLIST-Spalten kann 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:

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);

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:

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);

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.

SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([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:

SEARCH(AlbumTitle_Tokens, 'Blue Note') OR SEARCH(Studio_Tokens, 'Blue Note')

Dieser hat jedoch eine andere Semantik. Das ist nicht der Fall bei Alben, in denen AlbumTitle_Tokens „blau“ hat, aber nicht „Notiz“, und Studio_Tokens „Notiz“ hat, aber nicht „blau“.

Nächste Schritte