lakebase_tokenizer

lakebase_tokenizer拡張機能は、LakebaseのPostgreSQL全文検索に設定可能なトークン化を追加し、中国語、日本語、韓国語(CJK)テキストの全語処理や形態分析も含まれます。 拡張機能で構築されたテキスト検索構成は、 to_tsvector、 @@ 演算子、ランキング関数、GINインデックスと連携します。 生成された tsvector 値と lakebase_text を組み合わせてBM25のランキングを作成することもできます。

この拡張機能は、PostgreSQLの標準的なテキスト検索辞書インターフェースを通じて tokenizer_wholeword および tokenizer_morph テンプレートを提供します。 正規化、ストップワード、同義語、英語の語幹など、単語全体の処理には tokenizer_wholeword を使います。 CJK形態分析には tokenizer_morph をご利用ください。

Install

拡張機能をデータベースにインストールしてください。 このページの例は、拡張オブジェクトを容易に識別するために専用のスキーマを使用しています:

CREATE SCHEMA IF NOT EXISTS tokenizer_ext;
CREATE EXTENSION IF NOT EXISTS lakebase_tokenizer WITH SCHEMA tokenizer_ext;

延長は配置可能です。 インストール時に別のスキーマに置き換え tokenizer_ext 可能です。

拡張機能をアップグレードする

新しいLakebase Searchリリースは、機能、修正、パフォーマンス向上を追加できます。 PostgreSQLはインストールされた拡張機能のバージョンを自動的に更新しません。 インストール済みの最新バージョンを確認してください:

SELECT installed_version, default_version
FROM pg_available_extensions
WHERE name = 'lakebase_tokenizer';

拡張機能を最新の利用可能なバージョンに更新してください:

ALTER EXTENSION lakebase_tokenizer UPDATE;

ALTER EXTENSION 保存された tsvector 値を再生したり、依存するGINや lakebase_bm25 インデックスを再構築したりしません。 更新でトークン化出力が変更された場合は、保存された tsvector 値を再生成し、必要なインデックスメンテナンスのためにリリースノートに従ってください。

簡単スタート

テキストの言語に基づいて進路を選ぶ:

  • 英語やその他の空白区切り言語については、 tokenizer_wholeword テンプレートから辞書を作成します。
  • 中国語、日本語、韓国語のテキストには組み込みの設定を使います。 辞書を作る必要はありません。

全語テキスト

以下の例は、 tokenizer_wholeword テンプレートから辞書を作成し、一般的なPostgreSQLトークン型をテキスト検索構成でマッピングします。

CREATE TEXT SEARCH DICTIONARY documents_dict (
  TEMPLATE          = tokenizer_ext.tokenizer_wholeword,
  Lowercase         = 'true',
  StripAccents      = 'true',
  Stemmer           = 'english'
);

CREATE TEXT SEARCH CONFIGURATION documents_cfg (COPY = pg_catalog.simple);

ALTER TEXT SEARCH CONFIGURATION documents_cfg
  ALTER MAPPING FOR asciiword, word, numword, hword_numpart, hword_part, hword_asciipart
  WITH documents_dict;

この構成を使って tsvectorを作成し、GINインデックスを作成し、全文クエリを実行します:

CREATE TABLE documents (
  id            BIGSERIAL PRIMARY KEY,
  body          TEXT NOT NULL,
  search_vector TSVECTOR GENERATED ALWAYS AS (
    to_tsvector('documents_cfg', body)
  ) STORED
);

INSERT INTO documents (body) VALUES
  ('Cats are running near the café.'),
  ('A dog is sleeping in the house.');

CREATE INDEX documents_search_idx ON documents USING gin (search_vector);

SELECT id, body
FROM documents
WHERE search_vector @@ plainto_tsquery('documents_cfg', 'running café');

文書とクエリの両方に同じテキスト検索構成を用い、両者が同じトークン化戦略とオプションを適用できるようにします。

CJKテキスト

拡張機能をインストールすると、 tokenizer_chinese、 tokenizer_japanese、 tokenizer_korean テキスト検索の設定が作成されます。 そのうちの一つを直接使い、 tsvectorを作成し、GINインデックスを作成し、全文クエリを実行します。

中国語

CREATE TABLE chinese_documents (
  id            BIGSERIAL PRIMARY KEY,
  body          TEXT NOT NULL,
  search_vector TSVECTOR GENERATED ALWAYS AS (
    to_tsvector('tokenizer_ext.tokenizer_chinese', body)
  ) STORED
);

INSERT INTO chinese_documents (body) VALUES
  ('现代分布式文件系统架构');

CREATE INDEX chinese_idx ON chinese_documents USING gin (search_vector);

-- The built-in Chinese configuration uses mixed mode, so use plainto_tsquery instead of to_tsquery.
SELECT id, body
FROM chinese_documents
WHERE search_vector @@ plainto_tsquery('tokenizer_ext.tokenizer_chinese', '现代分布式');

Japanese

CREATE TABLE japanese_documents (
  id            BIGSERIAL PRIMARY KEY,
  body          TEXT NOT NULL,
  search_vector TSVECTOR GENERATED ALWAYS AS (
    to_tsvector('tokenizer_ext.tokenizer_japanese', body)
  ) STORED
);

INSERT INTO japanese_documents (body) VALUES
  ('関西国際空港へのアクセス');

CREATE INDEX japanese_idx ON japanese_documents USING gin (search_vector);

SELECT id, body
FROM japanese_documents
WHERE search_vector @@ to_tsquery('tokenizer_ext.tokenizer_japanese', '関西国際空港');

韓国語

CREATE TABLE korean_documents (
  id            BIGSERIAL PRIMARY KEY,
  body          TEXT NOT NULL,
  search_vector TSVECTOR GENERATED ALWAYS AS (
    to_tsvector('tokenizer_ext.tokenizer_korean', body)
  ) STORED
);

INSERT INTO korean_documents (body) VALUES
  ('선생님께서 도서관에 갑니다');

CREATE INDEX korean_idx ON korean_documents USING gin (search_vector);

SELECT id, body
FROM korean_documents
WHERE search_vector @@ to_tsquery('tokenizer_ext.tokenizer_korean', '선생님께서');

テンプレート: tokenizer_wholeword

どのように機能するのか

PostgreSQLのテキストサーチパーサーによって辞書に渡された各トークンに対して、 tokenizer_wholeword 以下の操作を適用します:

  1. Lowercase: トークンを小文字に変換してください。
  2. Normalize: Unicode正規化を適用してください。
  3. StripAccentsアクセントを取り除く。
  4. EnglishPossessive: 少なくとも1文字が残っている場合は英語所有接尾辞を外してください。
  5. Stopwords: トークンが設定されたストップワードに一致する場合は、語彙を放出せず処理を停止します。 トークンは生成された tsvectorから除外されます。
  6. Synonyms: 設定済みの置換を発行し、トークンが同義語に一致した場合は処理を停止します。
  7. Stemmer: 同義語が一致せず、語幹が有効の場合は英語語幹を適用します。

ストップワードや同義語の追加

tokenizer_wholewordテンプレートは、拡張管理のSQLテーブルlakebase_tokenizer_stopwordsおよびlakebase_tokenizer_synonymsからカスタムストップワードや同義語を読み込むことができます。 name列は行をグループ化し、Stopwordsまたは辞書Synonymsオプションで選択します。

INSERT INTO tokenizer_ext.lakebase_tokenizer_stopwords (name, word) VALUES
  ('app_stopwords', 'the'),
  ('app_stopwords', 'and'),
  ('app_stopwords', 'or');

INSERT INTO tokenizer_ext.lakebase_tokenizer_synonyms (name, word, synonym) VALUES
  ('app_synonyms', 'usa', 'united_states'),
  ('app_synonyms', 'uk', 'united_kingdom');

tokenizer_wholeword辞書を作成または変更する際には、集合を参照してください:

ALTER TEXT SEARCH DICTIONARY documents_dict (
  Stopwords = 'app_stopwords',
  Synonyms  = 'app_synonyms'
);

この拡張機能は、 Lowercase、 Normalize、 StripAccents、 EnglishPossessiveを適用した後、かつ Stemmerを適用する前に、各トークンとストップワードや同義語のソースワードを比較します。 カタログエントリーは自動的に変換されないため、有効にしたオプションで生成される正確な形式で保存してください。

  • Lowercase = 'true'では小文字のエントリを使いましょう。 Lowercase = 'false'では、大文字の大きさがトークンと一致しなければなりません。
  • Normalizeを有効にした状態で、選択したUnicode正規化フォームにエントリーを保存します。
  • StripAccents = 'true'ではアクセントのないフォームを保管してください。 例えば、caféに合わせてcafeを保存します。
  • ステムをする前にフォームを保管してください。 例えば、 Stemmer = 'english'の場合、 run の項目は runningと一致しません。 runningを追加してそのトークンをフィルターしたり置き換えたりしてください。

セット名は最大256バイトまで含めることができます。 単語や同義語は最大1024バイトまで含めることができます。 各名前付きストップワードまたはシノニムセットは最大100,000行を含みます。

同義語置換は保存されたままのまま放射され、ステマーによって処理されません。 同義語は、各出典語に対して1つの置き換えを推奨します。 複数語置換を1つの語素として表現するには、 united_statesのようにアンダースコアなどの区切り子を使います。

セットを変更した後、その集合を参照する各辞書の所有者は、リロードを強制するために no-op ALTER TEXT SEARCH DICTIONARY を実行しなければなりません。

ALTER TEXT SEARCH DICTIONARY documents_dict (dummy);

dummyオプションはtokenizer_wholewordには存在しません。 値を省略すると、PostgreSQLにこの存在しないオプションを削除してもらい、辞書の設定オプションを変更することなくキャッシュが無効化されます。

辞書を再読み込みした後、元の行を書き換えて保存された tsvector 値を再生成します:

UPDATE documents SET body = body;

役割とアクセス

アプリケーションアクセスとトークナイザー管理を分離するために2つの役割を使いましょう:

  • app_role 既存の辞書を使用しています。 関連するスキーマや拡張カタログテーブルのSELECTUSAGEが必要ですが、辞書を所有する必要はありません。
  • tokenizer_admin ストップワードおよびシノニムセットの管理、辞書およびテキスト検索構成の作成・所有、セット変更後にリロードコマンドを実行します。

拡張スキーマとカタログテーブルへのアクセスを許可する:

GRANT USAGE ON SCHEMA tokenizer_ext TO app_role, tokenizer_admin;

GRANT SELECT ON
  tokenizer_ext.lakebase_tokenizer_stopwords,
  tokenizer_ext.lakebase_tokenizer_synonyms
TO app_role;

GRANT SELECT, INSERT, UPDATE, DELETE ON
  tokenizer_ext.lakebase_tokenizer_stopwords,
  tokenizer_ext.lakebase_tokenizer_synonyms
TO tokenizer_admin;

tokenizer_admin 辞書やテキスト検索設定が格納されているスキーマにも CREATE が必要です。 これらのオブジェクトを tokenizer_adminとして作成するか、所有権を移転します。 カタログテーブルへの書き込みアクセスは既存の辞書の所有権を付与しません。

オプション

tokenizer_wholeword選択肢をCREATE TEXT SEARCH DICTIONARYまたはALTER TEXT SEARCH DICTIONARYで指定してください。 オプション名は大文字と大文字を区別しません。

オプション タイプ Default Description
Lowercase boolean true 他の操作を適用する前にトークンを小文字に変換します。 Stemmer = 'english' には Lowercase = 'true'が必要です。
Normalize NFC、NFD、NFKC、NFKD、または none none 選択したUnicode正規化形式を適用します。 これにより表現は正統化されますが、キャラクターは削除されません。 例えば、 NFC はあらかじめ構成された é と e を、その後に結合した急性アクセントの等価音を作っています。
EnglishPossessive boolean true 接尾辞の前に少なくとも1文字の文字が続く場合は、 's、 ’s、または 's の後ろを除去します。 独立した接尾辞は変更されていません。
StripAccents boolean false NFKD正規化を適用し、結合マークを除去します。 たとえば、café を cafe にします。 このオプションを有効にすると、NFKDステップにより個別のUnicode正規化が不要になるため、 Normalize を省略してください。
Stopwords セット名 なし tokenizer_ext.lakebase_tokenizer_stopwordsの命名された集合を使用しています。
Synonyms セット名 なし tokenizer_ext.lakebase_tokenizer_synonymsの1対1の代替セットを使用しています。
Stemmer english なし バンドルされたSnowball 3.1.0英語ステマーを使用しています。 ステミングを無効にするこのオプションは省略してください。 ステマーにはストップワードリストは含まれていません。

カタログ テーブル

テーブル Columns Description
lakebase_tokenizer_stopwords name text、word text 店舗は tokenizer_wholewordにストップワードセットと名付けられています。 主キーは (name, word) です。
lakebase_tokenizer_synonyms name text、word text、synonym text 店舗は1対1の代替者を指名 tokenizer_wholeword。 主キーは (name, word) です。

テンプレート: tokenizer_morph

tokenizer_morphテンプレートは、PostgreSQLの全文検索において中国語、日本語、韓国語のトークナイズをサポートしています。 組み込みのテキスト検索設定を使うか、用語生成を制御するためのカスタム設定を定義してください。

どのように機能するのか

tokenizer_morph Linderaアナライザーとバンドルされた辞書を使用します:中国語用にJieba、日本語用にIPADIC、韓国語用にMeCab KoDic。

韓国語のパーサートークンの場合、tokenizer_morphㆍ(U+318D)をトークン境界に置き換えます。

PostgreSQLのテキストサーチ解析器によって辞書に渡された各トークンに対して、 tokenizer_morph 以下の操作を順番に適用します。

  1. Normalize: パーサートークンにUnicode正規化を適用します。
  2. Language: 選択した言語アナライザーでパーサートークンをセグメント化します。
  3. シンボルフィルター:文字や数字を含まないセグメントを破棄します。
  4. 言語別分析:残った各セグメントを以下のように0つ以上の用語に変換します。
  5. Lowercase: 各項を小文字に変換します。
  6. Stemmer: 有効であれば、英語のステマーをバンドルしたASCII文字だけで構成する語幹項。 このステップはCJK用語を阻止するものではありません。

言語固有の分析ステップは以下のルールを適用します:

中国語

  • サブワードの拡張: mixed モードでは、バンドルされた辞書に含まれる2文字および3文字の用語を追加します。

日本語

  • 品詞フィルタリング:認識された助詞、助動詞、接続詞、フィラー、非言語音、非アルファベット記号、タグ付けされた区間を破棄 その他,間投。
  • 基底形変換:利用可能な場合は、残りの認識された各セグメントの辞書基底形を使用します。 そうでなければ、その表面的な形を保ちます。
  • ストップワードフィルタリング:一般的な日本語の機能語リストに合致する用語を破棄します。
  • 片假名語幹:少なくとも4文字の後ろの文字を、すべて片假名ブロックに属する(U+30A0からU+30FF)から後尾の ー 文字を削除します。

韓国語

  • 分解: discard モードおよび mixed モードで、辞書が構成要素を提供する際に認識された複合詞、屈折済み、または事前分析済みの区間を分割します。 discard は完全な項の代わりに成分を放出し、 mixed は両方を放出します。
  • 品詞フィルタリング:用語全体と各コンポーネントに独立してフィルタリングを適用します。 助詞、語尾、接辞、副詞、限定詞、感嘆詞、句読点、記号、または分析不可能な形などのタグ付けされた用語は省略してください。
  • ハングル読解変換:利用可能な場合は、辞書のハングル読解を使い、完全な語彙を保持してください。 コンポーネントは辞書形式を保ちます。

PostgreSQLのテキスト検索パーサーは、テキストを空白と句読点で分割してから tokenizer_morph呼び出します。 各パーサトークンは最大2046バイトを含め、長いトークンはNOTICEでスキップされます。 ほとんどの中国語、日本語、韓国語の文字はUTF-8で3バイトを使用しているため、空白や句読点なしの682文字以上の連続は結果から除外されます to_tsvector 。

対応言語とモード

利用可能なモードは言語によって異なります。 各例は、発信された語→ソーステキストを示しています:

Language Mode Behavior Example
中国語 none 短い検索語を加えずに標準的なセグメンテーションから単語を出力します。 现代分布式文件系统架构 → 现代、 分布式文件系统、 架构
中国語 mixed 標準的なセグメンテーションから単語を保持し、長い単語から短い検索語を追加します。 现代分布式文件系统架构 → 现代、 分布式文件系统、 分布、 分布式、 布式、 文件、 系统、 架构
Japanese none より長い辞書複合語を好む。 関西国際空港へのアクセス → 関西国際空港、 アクセス
Japanese discard 一部の長い化合物に対しては、完全な形を保持せずにより細かい項を生成する。 関西国際空港へのアクセス → 関西、 国際、 空港、 アクセス
韓国語 none 複合辞書や屈折辞書の項目を語彙としてまとめて保持します。 한국어 형태소 분석 → 한국어、 형태소、 분석
韓国語 discard 複合形や屈折形が分割される場合、その部分を発信します。 한국어 형태소 분석 → 한국、 어、 형태、 소、 분석
韓国語 mixed 複合形や屈折形が分割できる場合、その語全体とその部分の両方が発音されます。 한국어 형태소 분석 → 한국어、 한국、 어、 형태소、 형태、 소、 분석

mixedモードではplainto_tsqueryでクエリを行います。 1つのクエリワードが複数の語素、 to_tsquery、 websearch_to_tsquery、 phraseto_tsquery を <-> 演算子で結びつける場合、隣接する位置が必要です。 mixed モードは追加の項に位置を挿入するため、これらのフレーズ条件は予想されるマッチを見逃すことがあります。 ポジションベースのクエリでは、 none モードまたは discard モードでカスタム構成を定義してください。

組み込みの設定を活用してください

拡張機能をインストールすると、以下のテキスト検索構成が作成されます:

Configuration 辞書 Language Mode
tokenizer_chinese tokenizer_chinese_dict 中国語 mixed
tokenizer_japanese tokenizer_japanese_dict Japanese discard
tokenizer_korean tokenizer_korean_dict 韓国語 discard

3つの辞書はすべて Stemmer = 'english' を設定し、デフォルトの Normalize = 'NFKC' と Lowercase = 'true'を使用しています。

これらの構成を用いた端から端までの例については、 CJKのテキストを参照してください。

カスタム構成を定義する

別のモードを選択したりデフォルトオプションを変更したい場合は、 tokenizer_morph テンプレートから辞書を作成し、PostgreSQLトークン型をそれにマッピングするテキスト検索構成を作成します(以下参照)。 この例では、フレーズクエリに中国語 none モードを使用しています:

CREATE TEXT SEARCH DICTIONARY chinese_none_dict (
  TEMPLATE = tokenizer_ext.tokenizer_morph,
  Language = 'chinese',
  Mode = 'none',
  Stemmer = 'english'
);

CREATE TEXT SEARCH CONFIGURATION chinese_none_cfg (COPY = pg_catalog.simple);

ALTER TEXT SEARCH CONFIGURATION chinese_none_cfg
  ALTER MAPPING FOR asciiword, word, numword, hword_asciipart, hword_part, hword_numpart
  WITH chinese_none_dict;

SELECT to_tsvector('chinese_none_cfg', '现代分布式文件系统架构')
  @@ phraseto_tsquery('chinese_none_cfg', '分布式文件系统 架构');

オプション

tokenizer_morph選択肢をCREATE TEXT SEARCH DICTIONARYまたはALTER TEXT SEARCH DICTIONARYで指定してください。 オプション名は大文字と大文字を区別しません。

オプション タイプ Default Description
Language chinese、 japanese、または korean Required 言語固有のアナライザーを選択します。
Mode none、 discard、または mixed Required 複合語とサブワードの出力を制御します。 対応モードは Languageによって異なります。中国語は none または mixed 、日本語は none または discard 、韓国語は none、 discard、または mixed です。
Normalize NFC、 NFKC、または none NFKC セグメント化前にテキストを正規化します。 NFC 互換性の区別を保持します。 例えば、全幅ABCはabcに変換されるのではなく小文字で、小文字で表記されるabcであるため、茎付きではありません。
Lowercase boolean true 変換者はレクセムを小文字に発します。 Stemmer = 'english' には Lowercase = 'true'が必要です。
Stemmer english なし ASCII文字だけで構成された語幹のみの語彙。 英語の語幹を無効にするオプションは省略してください。

BM25のランキングをlakebase_textで使う

lakebase_tokenizerで構築されたテキスト検索構成は、lakebase_textと互換性のある標準的なPostgreSQLのtsvector値を生成します。 BM25の関連性ランキングとトップK検索を利用するには、同じtsvector列にlakebase_bm25インデックスを作成します。 インストール、インデックス作成、クエリ構文については lakebase_textを参照してください。

次のステップ