これはPGroonga 2.X and 3.X用のドキュメントです。古いPGroongaを使っているならPGroonga 1.xのドキュメントを見てください。

CREATE INDEX USING pgroonga

インデックスメソッドとしてPGroongaを使うためにはCREATE INDEXUSING pgroongaを指定します。このセクションではpgroongaインデックスメソッドについて説明します。

構文

このセクションではpgroongaインデックスメソッド関連のCREATE INDEXの構文だけ説明します。完全なCREATE INDEXの構文はPostgreSQLのCREATE INDEXのドキュメントを参照してください。

シングルカラムインデックスを作成する基本的な構文は次の通りです。

CREATE INDEX ${INDEX_NAME}
          ON ${TABLE_NAME}
       USING pgroonga (${COLUMN});

次のケースのときはこの構文を使えます。

varchar型のカラム用の全文検索インデックスを作るときの基本的な構文は次の通りです。

CREATE INDEX ${INDEX_NAME}
          ON ${TABLE_NAME}
       USING pgroonga (${COLUMN} pgroonga_varchar_full_text_search_ops_v2);

この場合はpgroonga_varchar_full_text_search_ops_v2オペレータークラスを指定する必要があります。

2.3.5からINCLUDEも使えます。

カスタマイズ

CREATE INDEXWITHオプションを使って次の項目をカスタマイズできます。

通常、これらをカスタマイズする必要はありません。なぜなら多くの場合で適切なようにデフォルト値が設定されているからです。これらをカスタマイズする機能は高度なユーザー向けの機能です。

デフォルトではプラグインとトークンフィルターは使われていません。

デフォルトのトークナイザーとノーマライザーと語彙表の種類は次の通りです。

プラグインの登録方法

1.2.0で追加。

プラグインを登録するにはplugins='${プラグイン名1}, ${プラグイン名2}, ..., ${プラグイン名N}'を指定します。

CREATE INDEXの最初のオプションとしてpluginsを指定しなければいけないことに注意してください。CREATE INDEXのオプションは指定された順に処理されます。指定したプラグインに含まれてるトークナイザー・ノーマライザー・トークンフィルターを使うかもしれないので、他のオプションより先にプラグインを登録しておく必要があります。

以下はTokenFilterStemトークンフィルターを使うためにtoken_filters/stemプラグインを登録する例です。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH (plugins='token_filters/stem',
              token_filters='TokenFilterStem');

トークンフィルターについてはトークンフィルターのカスタマイズ方法を参照してください。

トークナイザーのカスタマイズ方法

トークナイザーをカスタマイズするにはtokenizer='${トークナイザー名}'を指定します。通常、トークナイザーをカスタマイズする必要はありません。

以下はMeCabベースのトークナイザーを使う例です。tokenizer='TokenMecab'を指定する必要があります。TokenMecabはMeCabベースのトークナイザーの名前です。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH (tokenizer='TokenMecab');

tokenizer=''と指定することでトークナイザーを無効にすることができます。トークナイザーを無効にすると、完全一致検索または前方一致検索のみでカラムの値を検索できます。これにより誤ヒットが少なくなるケースがあります。例えば、タグ検索・名前検索などのときは有用です。

以下はトークナイザーを無効にする例です。

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
        WITH (tokenizer='');

tokenizer='TokenDelimit'はタグ検索で便利です。TokenDelimitも参照してください。

tokenizer='${TOKENIZER_NAME}(...)'という構文でトークナイザーのオプションを指定できます。

2.0.6から使えます。

以下は"n"オプションと3オプションを指定してTokenNgramトークナイザーを使う例です。

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
        WITH (tokenizer='TokenNgram("n", 3)');

他のトークナイザーについてはトークナイザーを参照してください。

Partial match in alphabetic languages

If you plan to perform partial matching searches for keywords in alphabetic languages, it is recommended to configure your tokenizer to TokenNgram with extra options. The default tokenizer in PGroonga is TokenBigram, which means that if you search for the keyword 'pp', for instance, it won't match 'Apple', 'Pineapple', or 'Ripple' in your data. To avoid this issue, it is strongly advised to set up your tokenizer as following TokenNgram example.

Here is an example to use TokenNgram based tokenizer. You need to specify tokenizer='TokenNgram'. See TokenNgram for more detail.

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH(tokenizer='TokenNgram("unify_alphabet", false, "unify_symbol", false, "unify_digit", false)');

You may also use TokenBigramBigramSplitSymbolAlphaDigit for partial match instead of TokenNgram above. (Using TokenNgram(...) is recommended).

Remarks We however do not recommend using TokenNgram("unify_...). It is advisable to use TokenNgram/TokenBigram instead, as partial matches in alphabetical languages tend to introduce a lot of noise. TokenNgram("unify_...) should only be utilized when it is truly necessary.

ノーマライザーのカスタマイズ方法

次のパラメーターを使ってノーマライザーをカスタマイズできます。通常、ノーマライザーをカスタマイズする必要はありません。

normalizers=''のように空の値を指定するとノーマライザーを無効にすることができます。ノーマライザーを無効にすると元のカラムの値そのものでだけ検索できます。もし、ノーマライザーを使うことで誤ヒットが増える場合は無効にした方がよいでしょう。

ノーマライザーを無効にする方法は次の通りです。

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
        WITH (normalizers='');

normalizers='${NORMALIZER_NAME}(...)'という構文でノーマライザーのオプションを指定できます。

2.0.6から使えます。

以下は"unify_kana"オプションとtrueオプションを指定してNormalizerNFKC100ノーマライザーを使う例です。

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
        WITH (normalizers='NormalizerNFKC100("unify_kana", true)');

normalizers='${NORMALIZER_NAME1}(...), ${NORMALISER_NAME2(...), ...'という構文で複数のノーマライザーを指定できます。

2.3.1から使えます。

以下は"unify_kana"trueというオプション付きのNormalizerNFKC130ノーマライザーと"unify_hyphen"trueというオプション付きのNormalizerNFKC130ノーマライザーを使う実用的ではない例です。

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
        WITH (normalizers='
                NormalizerNFKC130("unify_kana", true),
                NormalizerNFKC130("unify_hyphen", true)
              ');

他のノーマライザーについてはノーマライザーを参照してください。

全文検索・正規表現検索・前方一致検索それぞれに別のノーマライザーを使うこともできます。これらの検索用の代表的な演算子クラスは次の通りです。

次のパラメーターを使うことでそれぞれの検索方法ごとに異なるノーマライザーを使えます。

これらのパラメーターを使っていない場合はnormalizersパラメーターの値を使います。

以下は全文検索用のインデックスだけノーマライザーを無効にする例です。

CREATE TABLE memos (
  id integer,
  title text,
  content text,
  tag text
);

CREATE INDEX pgroonga_memos_index
          ON memos
       USING pgroonga (
               title pgroonga_text_full_text_search_ops_v2,
               content pgroonga_text_regexp_ops_v2,
               tag pgroonga_text_term_search_ops_v2
             )
        WITH (full_text_search_normalizer='',
              normalizers='NormalizerAuto');

titleのインデックスは全文検索用です。full_text_search_normalizer''なので、このインデックスはノーマライザーを使いません。normalizer'NormalizerAuto'なので、他のインデックスはNormalizerAutoを使います。

以下は正規表現検索用のインデックスだけノーマライザーを無効にする例です。

CREATE TABLE memos (
  id integer,
  title text,
  content text,
  tag text
);

CREATE INDEX pgroonga_memos_index
          ON memos
       USING pgroonga (
               title pgroonga_text_full_text_search_ops_v2,
               content pgroonga_text_regexp_ops_v2,
               tag pgroonga_text_term_search_ops_v2
             )
        WITH (regexp_search_normalizer='',
              normalizers='NormalizerAuto');

contentのインデックスは正規表現検索用です。regular_expression_search_normalizer''なので、このインデックスはノーマライザーを使いません。normalizers'NormalizerAuto'なので、他のインデックスはNormalizerAutoを使います。

以下は前方一致検索用のインデックスだけノーマライザーを無効にする例です。

CREATE TABLE memos (
  id integer,
  title text,
  content text,
  tag text
);

CREATE INDEX pgroonga_memos_index
          ON memos
       USING pgroonga (
               title pgroonga_text_full_text_search_ops_v2,
               content pgroonga_text_regexp_ops_v2,
               tag pgroonga_text_term_search_ops_v2
             )
        WITH (prefix_search_normalizer='',
              normalizers='NormalizerAuto');

tagのインデックスは単語検索用です。単語検索は前方一致検索も含んでいます。prefix_search_normalizer''なので、このインデックスはノーマライザーを使いません。normalizers'NormalizerAuto'なので、他のインデックスはNormalizerAutoを使います。

normalizers_mapping='${MAPPING_IN_JSON}'を使うと指定したインデックス対象用のノーマライザーを指定できます。

2.3.1から使えます。

以下は${MAPPING_IN_JSON}の構文です。

{
  "${index_target_name1}": "${normalizer1}",
  "${index_target_name2}": "${normalizer2}",
  ...
}

以下の例ではtitleNormalizerNFKC130("unify_kana", true)ノーマライザー、contentNormalizerNFKC130("unify_hyphen", true)ノーマライザー、それ以外のカラムにNormalizerAutoを指定しています。

CREATE TABLE memos (
  id integer,
  title text,
  content text,
  tag text
);

CREATE INDEX pgroonga_memos_index
          ON memos
       USING pgroonga (
               title pgroonga_text_full_text_search_ops_v2,
               content pgroonga_text_regexp_ops_v2,
               tag pgroonga_text_term_search_ops_v2
             )
        WITH (normalizers_mapping='{
                "title": "NormalizerNFKC130(\"unify_kana\", true)",
                "content": "NormalizerNFKC130(\"unify_hyphen\", true)"
              }',
              normalizers='NormalizerAuto');
NormalizerTableの使い方

ノーマライザーを指定するテキスト中で${table:PGROONGA_INDEX_NAME}という構文を使えます。

2.3.1から使えます。

この値はPGROONGA_INDEX_NAMEで指定したPGroongaのインデックスに対応するGroongaのテーブル名に置換されます。これはNormalizerTableを使うときに便利です。NormalizerTableはGroongaのテーブル名・カラム名を使うからです。

以下はNormalizerNFKC130ノーマライザーとNormalizerTableノーマライザーを使う例です。

CREATE TABLE normalizations (
  target text,
  normalized text
);

CREATE INDEX pgrn_normalizations_index ON normalizations
 USING pgroonga (target pgroonga_text_term_search_ops_v2,
                 normalized);

INSERT INTO normalizations VALUES ('o', '0');
INSERT INTO normalizations VALUES ('ss', '55');

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_memos_index
          ON memos
       USING pgroonga (content)
        WITH (normalizers='
                NormalizerNFKC130,
                NormalizerTable(
                  "normalized", "${table:pgrn_normalizations_index}.normalized",
                  "target", "target"
                )
             ');

INSERT INTO memos VALUES (1, '0123455');
INSERT INTO memos VALUES (2, 'o1234ss');

SELECT * FROM memos WHERE content &@~ 'o123455';
--  id | content 
-- ----+---------
--   1 | 0123455
--   2 | o1234ss
-- (2 rows)

normalizationsテーブルを変更した後はREINDEX INDEX pgroonga_memos_indexを実行しないといけないことに注意してください。なぜならnormalizationsテーブルが変わるとノーマライズ結果も変わるからです。

pgroonga_highlight_htmlと一緒にNormalizerTableを使う方法

このNormalizerTableと一緒にpgroonga_highlight_html関数を使うときは、TokenNgram"report_source_location", true"オプションを指定するだけでなく、NormalizerNFKC*NormalizerTableそれぞれに"report_source_offset", true"オプションを指定する必要があります。

詳細はpgroonga_highlight_html関数を参照してください。

トークンフィルターのカスタマイズ方法

1.2.0で追加。

トークンフィルターを使うにはtoken_filters='${トークンフィルター1}, ${トークンフィルター2}, ..., ${トークンフィルターN}'を指定します。

Groongaはデフォルトでは1つもトークンフィルターを提供していません。すべてのトークンフィルターはプラグインとして提供しています。トークンフィルターを使う場合はプラグインを登録する必要があります。

以下はtoken_filters/stemプラグインに含まれているTokenFilterStemトークンフィルターを使う例です。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH (plugins='token_filters/stem',
              token_filters='TokenFilterStem');

token_filtersより前にpluginsを指定しなければいけないことに注意してください。CREATE INDEXに指定したオプションは指定した順に処理されます。トークンフィルターを使う前にプラグインを登録しておく必要があります。

他のトークンフィルターについてはトークンフィルターを参照してください。

テーブルスペースのカスタマイズ方法

1.1.6で追加。

テーブルスペースをカスタマイズするにはTABLESPACE ${TABLESPACE_NAME}を指定してください。もし高速なストレージがある場合は、テーブルスペースを変更してそのストレージにPGroongaのインデックスを置きたくなるかもしれません。

以下はテーブルスペースを変更する例です。

CREATE TABLESPACE fast LOCATION '/data/fast_disk';

CREATE TABLE memos (
  id integer,
  tag text
);

CREATE INDEX pgroonga_tag_index
          ON memos
       USING pgroonga (tag)
  TABLESPACE fast;

語彙表の種類のカスタマイズ方法

2.0.6で追加。

語彙表の種類をカスタマイズするにはlexicon_type='${LEXICON_TYPE}'を指定します。

利用可能な語彙表の種類は次の通りです。

通常、これをカスタマイズする必要はありません。なぜなら多くの場合はデフォルト値が適切だからです。

以下はトークンの前方一致検索を無効にするために語彙表の種類をhash_tableにする例です。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH (lexicon_type='hash_table');

クエリーでcolumn:...構文を使う方法

2.1.3で追加。

クエリー中でcolumn:...構文を使うにはquery_allow_column=trueを指定します。

column:...構文を使うと、他のカラムを使ったり、マッチ以外の演算子も使うことができます。

column:...構文はシーケンシャルサーチでは動かないことに注意してください。インデックスサーチでしか動きません。

以下は同じインデックス内の他のカラムを使うためにquery_allow_columnを使う例です。

DROP TABLE IF EXISTS memos;
CREATE TABLE memos (
  title text,
  content text
);

CREATE INDEX pgroonga_memo_texts_index
          ON memos
       USING pgroonga (title, content)
        WITH (query_allow_column=true);

INSERT INTO memos VALUES
  ('PGroonga = PostgreSQL + Groonga', 'Very fast full text search extension.'),
  ('PostGIS', 'GIS extension.');

SELECT *
  FROM memos
    -- contentカラムは'extension'を含んでいて、かつ、
    -- titleカラムは'Groonga'を含んでいなければいけない。
 WHERE content &@~ 'extension title:@Groonga';
--               title              |                content                
-- ---------------------------------+---------------------------------------
--  PGroonga = PostgreSQL + Groonga | Very fast full text search extension.
-- (1 row)

以下は他の演算を使うためにquery_allow_columnを使う例です。

DROP TABLE IF EXISTS memos;
CREATE TABLE memos (
  title text
);

CREATE INDEX pgroonga_title_index
          ON memos
       USING pgroonga (title)
        WITH (query_allow_column=true);

INSERT INTO memos VALUES ('PGroonga');
INSERT INTO memos VALUES ('PGroonga = PostgreSQL + Groonga');

SELECT *
  FROM memos
    -- titleカラムは'PGroonga'でなければいけない。
    -- この演算はインデックスを使わないことに注意すること。
 WHERE title &@~ 'title:PGroonga';
--   title   
-- ----------
--  PGroonga
-- (1 row)

使える演算はGroongaのクエリー構文を参照してください。

インデックスカラムフラグのカスタマイズ方法

2.3.2で追加。

指定したインデックス対象のインデックスカラムフラグをカスタマイズするにはindex_flags_mappings='${MAPPING_IN_JSON}'を指定します。

以下は${MAPPING_IN_JSON}の構文です。

{
  "${index_target_name1}": ["${flag1_1}", "${flag1_2}", ..., "${flag1_N}"],
  "${index_target_name2}": ["${flag2_1}", "${flag2_2}", ..., "${flag2_N}"],
  ...
}

以下は利用可能なインデックスカラムのフラグです。それぞれGroongaのフラグに対応しています。

["SMALL", "MEDIUM", "LARGE"]というように競合するフラグを同時に指定することはできません。

通常、これをカスタマイズする必要はありません。なぜなら多くの場合はデフォルト値が適切だからです。

以下は大量データのために大きいインデックスカラムを使う例です。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content)
        WITH (index_flags_mapping='{
                "content": ["LARGE"]
              }');