このページでは、テーブルにトークン化を追加する方法について説明します。トークン化は、検索インデックスで使用されるトークンを作成するために必要です。
トークン化とは、値をトークンに変換するプロセスです。ドキュメントのトークン化に使用する方法によって、ユーザーがドキュメントに対して実行できる検索の種類と効率が決まります。
Spanner には、自然言語テキスト、部分文字列、文字列テキスト、数値、ブール値のトークナイザーが用意されています。データベース スキーマは、列に必要な検索の種類に一致するトークナイザーを使用します。トークナイザーには次の特徴があります。
- 各トークナイザーは、文字列や数値などの入力と、追加オプションの名前付き引数を取得する SQL 関数です。
- トークナイザーは
TOKENLIST
を出力します。
たとえば、テキスト文字列 The quick brown fox jumps over the lazy dog
は [the,quick,brown,fox,jumps,over,the,lazy,dog]
にトークン化されます。HTML 文字列 The <b>apple</b> is <i>red</i>
は [the,apple,is,red]
にトークン化されます。
トークンには次の特徴があります。
- トークンは、
TOKENLIST
データ型を使用する列に保存されます。 - 各トークンは、関連する属性のセットをオプションで指定して、バイトのシーケンスとして保存されます。たとえば、全文検索アプリケーションでは、トークンは通常、テキスト ドキュメントの単一の単語です。
- HTML 値をトークン化するときに、Spanner はドキュメント内のトークンの重要度を示す属性を生成します。Spanner は、これらの属性を使用してスコアリングを行い、より目立つ用語(見出しなど)を強調します
トークナイザー
Spanner は、次のトークナイザー関数をサポートしています。
全文トークナイザー(
TOKENIZE_FULLTEXT
)は、自然言語クエリの単語全体のトークンを生成します。例
次の両方の関数
GoogleSQL
TOKENIZE_FULLTEXT("Yellow apple") TOKENIZE_FULLTEXT("Yellow <b>apple</b>", content_type=>"text/html")
PostgreSQL
この例では
spanner.tokenize_fulltext
を使用しています。spanner.tokenize_fulltext("Yellow apple") spanner.tokenize_fulltext('Yellow <b>apple</b>', context_type=>'text/html')
同じトークン(
[yellow,apple]
)を生成します。部分文字列トークナイザー(
TOKENIZE_SUBSTRING
)は、各単語の各 n-gram のトークンを生成します。テキスト内の単語の部分文字列を検索するために使用されます。例
GoogleSQL
TOKENIZE_SUBSTRING('hello world', ngram_size_min=>4, ngram_size_max=>6)
PostgreSQL
この例では
spanner.tokenize_substring
を使用しています。spanner.tokenize_substring('hello world', ngram_size_min=>4, ngram_size_max=>6)
[ello,hell,hello,orld,worl,world]
というトークンを生成します。n-gram トークナイザー(
TOKENIZE_NGRAMS
)は、入力から n-gram を生成します(個別の単語に分割しません)。正規表現述語を高速化するために使用されます。例
次の関数:
GoogleSQL
TOKENIZE_NGRAMS("Big Time", ngram_size_min=>4, ngram_size_max=>4)
PostgreSQL
この例では
spanner.tokenize_ngrams
を使用しています。spanner.tokenize_ngrams('big time', ngram_size_min=>4, ngram_size_max=>4)
["Big ","ig T","g Ti"," Tim", "Time"]
というトークンを生成します。完全一致トークナイザー(
TOKEN
とTOKENIZE_BOOL
)は、いずれかの列に特定の値を含む行を検索するために使用されます。たとえば、商品カタログにインデックスを付けるアプリでは、特定のブランドと色の商品を検索する場合があります。例
次の関数:
GoogleSQL
TOKEN("hello") TOKEN(["hello", "world"])
PostgreSQL
この例では
spanner.token
を使用しています。spanner.token('hello')
[hello]
というトークンを生成します。次の関数:
GoogleSQL
TOKENIZE_BOOL(true)
PostgreSQL
この例では
spanner.tokenize_bool
を使用しています。spanner.tokenize_bool(true)
[y]
というトークンを生成します。数値トークナイザー(
TOKENIZE_NUMBER
)は、数値比較検索を高速化する一連のトークンを生成するために使用されます。等価条件の場合、トークンは数値そのものです。範囲条件(rating >= 3.5
など)の場合、トークンのセットはより複雑になります。例
次の関数ステートメント:
GoogleSQL
TOKENIZE_NUMBER(42, comparison_type=>'equality') TOKENIZE_NUMBER(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)
PostgreSQL
この例では
spanner.tokenize_number
を使用しています。spanner.tokenize_number(42, comparison_type=>'equality') spanner.tokenize_number(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)
"==42"
、"==42"
、"[1,75]"
、"[36, 45]"
、"[36,55]"
、"[36, 75]"
の各トークンを生成します。JSON トークナイザーと JSONB トークナイザー(
TOKENIZE_JSON
とTOKENIZE_JSONB
)は、JSON の包含とキーの存在述語(doc[@key] IS NOT NULL
(GoogleSQL)やdoc ? 'key'
(PostgreSQL)など)を高速化する一連のトークンを生成するために使用されます。
トークン化関数は通常、生成された列式で使用されます。これらの列は HIDDEN
として定義されているため、SELECT *
クエリ結果には含まれません。
次の例では、全文トークナイザーと数値トークナイザーを使用して、音楽アルバムの名前と評価を格納するデータベースを作成します。DDL ステートメントは次の 2 つの処理を行います。
- データ列
AlbumTitle
とRating
を定義します。 AlbumTitle_Tokens
とAlbumRating_Tokens
を定義します。これらのTOKENLIST
列は、Spanner がインデックスを付けられるように、データ列の値をトークン化します。GoogleSQL
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), Rating FLOAT64, AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN ) PRIMARY KEY(AlbumId);
PostgreSQL
CREATE TABLE albums ( albumid character varying NOT NULL, albumtitle character varying, albumtitle_Tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN, PRIMARY KEY(albumid));
ベース値が変更されるたびに、AlbumTitle_Tokens
と Rating_Tokens
が自動的に更新されます。
プレーン テキストまたは HTML コンテンツをトークン化する
テキストのトークン化は、プレーン テキストと HTML のコンテンツ タイプをサポートしています。Spanner の TOKENIZE_FULLTEXT
関数を使用してトークンを作成します。次に、CREATE SEARCH INDEX
DDL ステートメントを使用して検索インデックスを生成します。
たとえば、次の CREATE TABLE
DDL ステートメントは、TOKENIZE_FULLTEXT
関数を使用して、Albums
テーブルの AlbumTitles
からトークンを作成します。CREATE SEARCH INDEX
DDL ステートメントは、新しい AlbumTitles_Tokens
を使用して検索インデックスを作成します。
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(AlbumTitle_Tokens)
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(albumtitle_tokens)
トークン化プロセスでは、次のルールが使用されます。
- トークン化には、ステミングやスペルミスの修正は含まれません。たとえば、「A cat was looking at a group of cats」という文では、トークン「cat」はトークン「cats」とは別にインデックスに登録されます。書き込み時にトークンを正規化する他の検索エンジンとは異なり、Spanner には、検索クエリを拡張してさまざまな形式の単語を含めるオプションがあります。詳細については、拡張クエリモードをご覧ください。
- 検索インデックスには、一般的な単語(「a」など)が含まれます。
- 全文検索では、大文字と小文字は区別されません。トークン化プロセスでは、すべてのトークンが小文字に変換されます。
トークン化プロセスでは、元のテキスト内の各トークンの位置を追跡します。これらの位置は、後でフレーズを照合するために使用されます。位置情報は、ドキュメント ID とともに検索インデックスに保存されます。
Google はトークン化アルゴリズムの改善に継続的に取り組んでいます。今後、文字列が現在とは異なる方法でトークン化される可能性があります。このようなケースは非常にまれです。たとえば、中国語、日本語、韓国語(CJK)の言語のセグメント化が改善された場合です。
content_type
引数は、コンテンツ形式でプレーン テキストと HTML のどちらを使用するかを指定します。次の設定を使用して content_type
を設定します。
- テキスト トークン化の場合は、
content_type
引数をtext/plain
に設定します。これはデフォルト設定です。 - HTML トークン化の場合は、
content_type
引数を"text/html
に設定します。この引数を指定しないと、HTML タグは句読点として扱われます。HTML モードでは、Spanner はヒューリスティクスを使用して、ページ上のテキストの視認性を推測します。たとえば、テキストがヘッダーに含まれているかどうか、フォントサイズなどです。HTML でサポートされている属性には、small
、medium
、large
、title
、link などがあります。位置情報と同様に、属性は検索インデックス内のトークンとともに保存されます。トークン化では、HTML タグのトークンは作成されません。
トークン属性は、SEARCH
関数または SEARCH_SUBSTRING
関数の一致や結果には影響しません。ランキングにのみ使用されます。
次の例は、テキストをトークン化する方法を示しています。
GoogleSQL
CREATE TABLE T (
...
Text STRING(MAX),
Html STRING(MAX),
Text_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Text, content_type=>"text/plain")) HIDDEN,
Html_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Html, content_type=>"text/html")) HIDDEN
) PRIMARY KEY(...);
PostgreSQL
CREATE TABLE t (
...
text character varying,
html character varying,
text_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(text, content_type=>"text/plain")) VIRTUAL HIDDEN,
html_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(html, content_type=>'type/html')) VIRTUAL HIDDEN,
PRIMARY KEY(...));
language_tag
引数による言語検出の絞り込み
トークン化では、デフォルトで入力言語が自動的に検出されます。入力言語が判明している場合は、language_tag
引数を使用してこの動作を絞り込むことができます。
GoogleSQL
AlbumTitle_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(AlbumTitle, language_tag=>"en-us")) HIDDEN
PostgreSQL
albumtitle_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle, language_tag=>'en-us')) VIRTUAL HIDDEN
ほとんどのアプリでは、language_tag
引数を指定せず、自動言語検出に依存しています。中国語、韓国語、日本語などのアジア言語のセグメント化では、トークン化言語を設定する必要はありません。
次の例は、language_tag
がトークン化に影響するケースを示しています。
トークン化関数 | 生成されたトークン |
---|---|
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que") |
[a, tout, pourquoi, il, ya, un, parce, que] |
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que", \ language_tag=>"fr" ) |
[a, tout, pourquoi, il, y, a, un, parce, que] |
TOKENIZE_FULLTEXT("旅 行") |
2 つのトークン: [旅, 行] |
TOKENIZE_FULLTEXT("旅 行", language_tag=>"zh") |
1 つのトークン: [旅行] |
次のステップ
- 検索インデックスについて確認する。
- 数値インデックスについて確認する。
- インデックスのパーティショニングについて確認する。