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

LIKE演算子

概要

PGroongaは内部的にcolumn LIKE '%キーワード%'条件をcolumn %% 'キーワード'条件に変換します。%%演算子はインデックスを使って全文検索をします。これはインデックスを使わないLIKE演算子より速いです。

インデックスを使ったcolumn LIKE '%キーワード%'column %% 'キーワード'よりも遅いです。これは、インデックスを使ったcolumn LIKE '%キーワード%'は「再検査」する必要があるからです。column %% 'キーワード'は「再検査」する必要がありません。

元のLIKE演算子は対象テキストに対して検索します。しかし、%%演算子は正規化したテキストに対して検索します。そのため、インデックスを使ってLIKE演算子の検索を実行した場合は「再検査」が必要になります。

演算子クラス

この演算子を使うには次のどれかの演算子クラスを指定する必要があります。

構文

この演算子の構文は次の通りです。

column LIKE pattern

columnは検索対象のカラムです。

patternは検索パターンです。text型です。

使い方

例に使うサンプルスキーマとデータは次の通りです。

CREATE TABLE memos (
  id integer,
  content text
);

CREATE INDEX pgroonga_content_index ON memos USING pgroonga (content);
INSERT INTO memos VALUES (1, 'PostgreSQLはリレーショナル・データベース管理システムです。');
INSERT INTO memos VALUES (2, 'Groongaは日本語対応の高速な全文検索エンジンです。');
INSERT INTO memos VALUES (3, 'PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。');
INSERT INTO memos VALUES (4, 'groongaコマンドがあります。');

インデックスを使ってLIKE演算子を実行できます。

SET enable_seqscan = off;
SET enable_indexscan = on;
SET enable_bitmapscan = on;

SELECT * FROM memos WHERE content LIKE '%groonga%';
--  id |           content           
-- ----+-----------------------------
--   4 | groongaコマンドがあります。
-- (1 row)

PGroongaのインデックスが適用しているtext型用のデフォルトのオペレータークラスは、キーワードがアルファベットのみだった場合、キーワードの一部だけで検索してもヒットしません。たとえば、roongaというキーワードではヒットしません。

SET enable_seqscan = off;
SET enable_indexscan = on;
SET enable_bitmapscan = on;

SELECT * FROM memos WHERE content LIKE '%roonga%';
--  id | content 
-- ----+---------
-- (0 rows)

インデックスを使わない場合はroongaというキーワードでもヒットします。

SET enable_seqscan = on;
SET enable_indexscan = off;
SET enable_bitmapscan = off;

SELECT * FROM memos WHERE content LIKE '%roonga%';
--  id |                                  content                                  
-- ----+---------------------------------------------------------------------------
--   2 | Groongaは日本語対応の高速な全文検索エンジンです。
--   3 | PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。
--   4 | groongaコマンドがあります。
-- (3 rows)

キーワードがアルファベットだけだった場合でも、Groのようにキーワードの先頭部分を指定した場合はヒットします。

SET enable_seqscan = off;
SET enable_indexscan = on;
SET enable_bitmapscan = on;

SELECT * FROM memos WHERE content LIKE '%Gro%';
--  id |                                  content                                  
-- ----+---------------------------------------------------------------------------
--   2 | Groongaは日本語対応の高速な全文検索エンジンです。
--   3 | PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。
-- (2 rows)

キーワードがアルファベットの場合でも、キーワードの一部で検索できるようにする方法は2つあります。

最初の方法はTokenBigramSplitSymbolAlphaDigitトークナイザーを使う方法です。

DROP INDEX IF EXISTS pgroonga_content_index;

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

これでroongaでもヒットするようになります。

SET enable_seqscan = off;
SET enable_indexscan = on;
SET enable_bitmapscan = on;

SELECT * FROM memos WHERE content LIKE '%roonga%';
--  id |                                  content                                  
-- ----+---------------------------------------------------------------------------
--   2 | Groongaは日本語対応の高速な全文検索エンジンです。
--   3 | PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。
--   4 | groongaコマンドがあります。
-- (3 rows)

トークナイザーをカスタマイズする方法についてはCREATE INDEX USING pgroongaのカスタマイズを参照してください。

2つめの方法はpgroonga_text_regexp_opsオペレータークラスを使う方法です。

DROP INDEX IF EXISTS pgroonga_content_index;

CREATE INDEX pgroonga_content_index
          ON memos
       USING pgroonga (content pgroonga_text_regexp_ops_v2);

これでroongaでもヒットするようになります。

SET enable_seqscan = off;
SET enable_indexscan = on;
SET enable_bitmapscan = on;

SELECT * FROM memos WHERE content LIKE '%roonga%';
--  id |                                  content                                  
-- ----+---------------------------------------------------------------------------
--   2 | Groongaは日本語対応の高速な全文検索エンジンです。
--   3 | PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。
--   4 | groongaコマンドがあります。
-- (3 rows)

参考