このページでは、全文データと非テキストデータを組み合わせて検索する方法について説明します。
全文検索と非テキスト検索を組み合わせて実行する
検索インデックスは、全文検索、完全一致、数値列、JSON/JSONB 列をサポートしています。複数列の検索クエリと同様に、WHERE 句でテキスト条件と非テキスト条件を組み合わせることができます。クエリ オプティマイザは、検索インデックスを使用してテキスト以外の述語を最適化しようとします。検索インデックスに一致する行が 1 つしかない場合は、Spanner は条件を評価しません。一致する行が複数ある場合は、Spanner は検索インデックスに一致するすべての行の条件を評価します。検索インデックスに格納されていない参照列は、ベーステーブルからフェッチされます。
次に例を示します。
GoogleSQL
CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  Title STRING(MAX),
  Rating FLOAT64,
  Genres ARRAY<STRING(MAX)>,
  Likes INT64,
  Cover BYTES(MAX),
  Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
  Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN,
  Genres_Tokens TOKENLIST AS (TOKEN(Genres)) HIDDEN
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex
ON Albums(Title_Tokens, Rating_Tokens, Genres_Tokens)
STORING (Likes);
PostgreSQL
Spanner PostgreSQL のサポートには次の制限事項があります。
spanner.tokenize_number関数はbigint型のみをサポートします。spanner.tokenは配列のトークン化をサポートしていません。
CREATE TABLE albums (
  albumid character varying NOT NULL,
  title character varying,
  rating bigint,
  genres character varying NOT NULL,
  likes bigint,
  cover bytea,
  title_tokens spanner.tokenlist AS (spanner.tokenize_fulltext(title)) VIRTUAL HIDDEN,
  rating_tokens spanner.tokenlist AS (spanner.tokenize_number(rating)) VIRTUAL HIDDEN,
  genres_tokens spanner.tokenlist AS (spanner.token(genres)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex
ON albums(title_tokens, rating_tokens, genres_tokens)
INCLUDE (likes);
このテーブルに対するクエリの動作は次のとおりです。
RatingとGenresは検索インデックスに含まれます。Spanner は、検索インデックスの投稿リストを使用して条件を高速化します。ARRAY_INCLUDES_ANYとARRAY_INCLUDES_ALLは GoogleSQL 関数であり、PostgreSQL 言語ではサポートされていません。SELECT Album FROM Albums WHERE Rating > 4 AND ARRAY_INCLUDES_ANY(Genres, ['jazz'])クエリでは、全文述語と非テキスト述語を組み合わせるなど、任意の方法で結合、除外、否定を組み合わせることが可能です。このクエリは、検索インデックスによって完全に高速化されます。
SELECT Album FROM Albums WHERE (SEARCH(Title_Tokens, 'car') OR Rating > 4) AND NOT ARRAY_INCLUDES_ANY(Genres, ['jazz'])Likesはインデックスに格納されますが、スキーマは Spanner に対して、有効な値のトークン インデックスの作成をリクエストしません。したがって、Titleの全文述語とRatingの非テキスト述語は高速化されますが、Likesの述語は高速化されません。Spanner では、このクエリによって、Titleに「car」というキーワードが含まれ、評価が 4 より大きいすべてのドキュメントが取得され、高評価が 1,000 件未満のドキュメントが除外されます。ほとんどのアルバムのタイトルに「car」という単語が含まれ、ほとんどのアルバムの評価が 5 で、高評価が 1,000 件のアルバムが少ない場合は、このクエリで大量のリソースが使用されます。このような場合は、Ratingと同様にLikesをインデックスに登録するとリソースを節約できます。GoogleSQL
SELECT Album FROM Albums WHERE SEARCH(Title_Tokens, 'car') AND Rating > 4 AND Likes >= 1000PostgreSQL
SELECT album FROM albums WHERE spanner.search(title_tokens, 'car') AND rating > 4 AND likes >= 1000Coverはインデックスに保存されません。次のクエリは、AlbumsIndexとAlbumsの間でバック結合を行い、一致するすべてのアルバムのCoverを取得します。GoogleSQL
SELECT AlbumId, Cover FROM Albums WHERE SEARCH(Title_Tokens, 'car') AND Rating > 4PostgreSQL
SELECT albumid, cover FROM albums WHERE spanner.search(title_tokens, 'car') AND rating > 4
次のステップ
- 全文検索クエリについて確認する。
 - 検索結果をランク付けする方法を確認する。
 - 部分文字列検索を行う方法を確認する。
 - 検索結果をページ分けする方法を確認する。
 - 複数の列を検索する方法を確認する。