横断検索機能 とは
プリザンターには画面右上に検索ボックスがあり、こちらに入力した文字列をもとに各サイト(フォルダ、テーブル等)に登録された情報をサイトをまたいで(横断して)検索する機能があります。
この機能はデータベースの全文検索の仕組みを用いており、プリザンターではpg_trgmでフルテキストのインデックスを構築し、構築したインデックスをもとに検索を行います。
【参考情報】
PGroonga とは
PGroongaはPostgreSQLを高速に日本語全文検索可能なシステムにする拡張機能です。
インストールして使ってみる
チュートリアルを参考にインストール、インデックス作成、検索してみます。
インストール
環境に合わせてPGroongaのパッケージをインストールする。
プリザンターのデータベース(Implem.Pleasanter)に接続し、拡張機能(pgroonga)を追加します。
Implem.Pleasanter=# create extension pgroonga;
CREATE EXTENSION
Implem.Pleasanter=# \dx
List of installed extensions
Name | Version | Schema | Description
----------+---------+-------------------+--------------------------------------------------------------------------------
pg_trgm | 1.6 | Implem.Pleasanter | text similarity measurement and index searching based on trigrams
pgcrypto | 1.3 | Implem.Pleasanter | cryptographic functions
pgroonga | 3.2.0 | Implem.Pleasanter | Super fast and all languages supported full text search index based on Groonga
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(4 rows)
Implem.Pleasanter=#
インデックス作成
ItemsテーブルのFullTextカラムに対してインデックスを作成します。
Implem.Pleasanter=# create index pgroonga_fulltext_index on "Items" using pgroonga ("FullText");
作成することができました。
Implem.Pleasanter=# select * from pg_indexes where tablename = 'Items' and indexdef like '%FullText%';
schemaname | tablename | indexname | tablespace | indexdef
-------------------+-----------+-------------------------+------------+-------------------------------------------------------------------------------------------------
Implem.Pleasanter | Items | pgroonga_fulltext_index | | CREATE INDEX pgroonga_fulltext_index ON "Implem.Pleasanter"."Items" USING pgroonga ("FullText")
(1 row)
Implem.Pleasanter=#
検索
explainコマンドでクエリの実行計画を見てみると、インデックス(pgroonga_fulltext_index)が使用されていることを確認しました。
Implem.Pleasanter=# explain analyze select * from "Items" where "FullText" &@ '東京都';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.25..46035.26 rows=1000 width=290) (actual time=21.744..273.715 rows=21473 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Bitmap Heap Scan on "Items" (cost=0.25..44935.26 rows=417 width=290) (actual time=7.293..164.177 rows=7158 loops=3)
Recheck Cond: ("FullText" &@ '東京都'::text)
Heap Blocks: exact=8233
-> Bitmap Index Scan on pgroonga_fulltext_index (cost=0.00..0.00 rows=26522 width=0) (actual time=18.608..18.608 rows=21473 loops=1)
Index Cond: ("FullText" &@ '東京都'::text)
Planning Time: 82.987 ms
Execution Time: 276.227 ms
(10 rows)
Implem.Pleasanter=#
Implem.Pleasanter=# select count(*) from "Items" where "FullText" &@ '東京都';
count
-------
21473
(1 row)
ソースコードに手を加えてみる
ソースコードで該当する処理はこちらになります。
https://github.com/Implem/Implem.Pleasanter/blob/8101487bd3452e6106542a5f9e38d0fc69663323/Rds/Implem.PostgreSql/PostgreSqlCommandText.cs#L86
ソースコードを以下のように修正します。「%>」を「&@」に変更する。
public string CreateFullTextWhereItem(
string itemsTableName,
string paramName,
bool negative)
{
return (negative
? $"(not (coalesce(\"{itemsTableName}\".\"FullText\",'') &@ @{paramName}#CommandCount#))"
: $"(\"{itemsTableName}\".\"FullText\" &@ @{paramName}#CommandCount#)");
}
今回は「&@」を使用しましたが、全文検索する際に使用できる演算子は他にもあるようです。下記リファレンスの「演算子」に記載があります。
横断検索機能(PGroonga)試してみる
プリザンターに登録されているサンプルデータをもとに、「東京都」で検索してヒットした件数は、上記のクエリで確認した件数と一致していました。
さいごに
今回の記事をきっかけに引き続きPGroongaについて深掘りしていきたいと思います!