Rabbit Slide Show

MySQL・PostgreSQL上で動かす全文検索エンジン「Groonga」セミナー

2017-08-01

Description

MySQL・MariaDB・PostgreSQLを使ってリッチな全文検索システムを実装する方法を紹介します。 リッチな全文検索システムとは、単に全文検索できるだけではありません。全文検索できることはもちろん、クリックによる絞り込みや入力補完・関連エントリーの提示など、ユーザーが目的の情報をより簡単に見つけられるようにする機能があります。 全文検索エンジンGroongaをMySQL・MariaDB・PostgreSQLに組み込むことでSQLを使ってそんなリッチな全文検索システムを実装できます。

Text

Page: 1

Mroonga・PGroongaを使った
全文検索システムの実装方法
須藤功平
株式会社クリアコード
MySQL・PostgreSQL上で動かす全文検索エンジン「Groonga」セミナ
ー
2017-08-01
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 2

全文検索システム
対象
大量のテキスト
例:Wikiのデータ
例:オフィス文書のテキスト
例:商品説明・口コミ
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 3

全文検索システム
目的
必要な情報を
必要なときに
活用
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 4

必要な情報を活用
×
探している情報が見つからない
○
探している情報が見つかる
◎
意識していなかったけど
実は欲しかった情報も見つかる!
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 5

必要なときに活用
×
なかなか見つからない
○
すぐに見つかる
◎
すでに見つかっていた
例:レコメンデーション
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 6

実装方法
選択肢
全文検索サーバーを使う
RDBMSを使う
MySQL・MariaDB・PostgreSQLを使う
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 7

全文検索サーバー案
メリット
必要な機能が揃っている
+αの機能もある
速い
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 8

全文検索サーバー案
デメリット
実装コスト大
それぞれ独自の使い方だから
マスターデータの同期はどうする?
メンテナンスコスト大
それぞれ独自の仕組みだから
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 9

RDBMS案
メリット
実装コスト小
新しく覚えることが少ない
データの一元管理
メンテナンスコスト小
既存の運用ノウハウを使える
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 10

RDBMS案
デメリット
組込機能では機能不足
SQLの表現力不足
1クエリーで実現できない機能アリ
↑は性能を出しにくい
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 11

実現方法
第3の選択肢
RDBMS経由(SQL)で
全文検索エンジンを使う
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 12

メリット
高速で豊富な機能
実装コスト小
メンテナンスコスト小
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 13

デメリット
RDBMSに拡張機能が必要
DBaaSで使えない
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 14

オススメの選択肢
全文検索の知識ナシ
まだ単純な機能で十分
データ少:RDBMS単独でLIKE
(数十万件とか)
データ中:RDBMS組込全文検索機能
いまどきの全文検索機能が必要
RDBMS経由で全文検索エンジン
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 15

オススメの選択肢
全文検索の知識アリ
カリカリにチューニングしたい
RDBMSと全文検索サーバーを併用
それ以外
RDBMS経由で全文検索エンジン
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 16

説明する選択肢
RDBMS経由で
全文検索
エンジン
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 17

全文検索エンジン
Groonga(ぐるんが)
組込可能な全文検索エンジン
MySQL・MariaDBに組込→Mroonga
PostgreSQLに組込→PGoonga
全文検索サーバーとして
単独でも使用可能
RDBMSと全文検索サーバーを併用
もできる
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 18

Groongaの得意なこと
データの追加・更新
新鮮な情報をすぐに検索可能に!
更新中も検索性能を落とさない!
日本語
開発者が日本人
便利機能が組み込み
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 19

Mroonga(むるんが)
MySQLのストレージエンジン
InnoDB・MyISAMなどと同じレイヤー
使用方法
CREATE TABLE (...)
ENGINE=Mroonga
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 20

MySQL組込の全文検索機能
MySQL:5.7から使える
InnoDB+日本語対応パーサー
MariaDB:10.0.15から使える
Mroongaをバンドル
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 21

全文検索機能:基本
AND/OR/
NOT対応
ハイライ
ト
周辺テキ
スト表示
InnoDB
○ Mroonga
○
× ○
× ○
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 22

ハイライト
周辺テキスト表示
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 23

全文検索機能:高度な機能
入力補完
類似文書
検索
クエリー
展開
InnoDB
×
○ Mroonga
○
○
○ ○
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 24

全文検索性能の違い
計測データ
対象:Wikipedia日本語版
レコード数:約185万件
データサイズ:約7GB
メモリー4GB・SSD250GB (ConoHa)
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 25

検索性能1
キーワード:テレビアニメ
(ヒット数:約2万3千件)
InnoDB ngram
InnoDB MeCab
Mroonga:1
Mroonga・PGroongaを使った 全文検索システムの実装方法
3m2s
6m20s
0.11s
Powered by Rabbit 2.2.1

Page: 26

検索性能2
キーワード:データベース
(ヒット数:約1万7千件)
InnoDB ngram
InnoDB MeCab:1
Mroonga:2
Mroonga・PGroongaを使った 全文検索システムの実装方法
36s
0.03s
0.09s
Powered by Rabbit 2.2.1

Page: 27

検索性能3
キーワード:PostgreSQL OR MySQL
(ヒット数:約400件)
InnoDB ngram
N/A(Error)
InnoDB MeCab:1
0.005s
Mroonga:2
0.028s
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 28

検索性能4
キーワード:日本
(ヒット数:約63万件)
InnoDB ngram
InnoDB MeCab
Mroonga:1
Mroonga・PGroongaを使った 全文検索システムの実装方法
1.3s
1.3s
0.21s
Powered by Rabbit 2.2.1

Page: 29

検索性能まとめ
Mroonga:安定して速い
SQLで使えて機能豊富で速い!
InnoDB FTS MeCab
ハマれば速い
InnoDB FTS ngram
安定して遅い
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 30

全文検索システムの実装
Mroonga
全文検索
キーワードハイライト
周辺テキスト表示
入力補完
関連文書の表示
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 31

全文検索
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 32

テーブル定義
CREATE TABLE entries (
title text,
content text,
-- 全文検索用インデックス
-- よくわからないならデフォルトのまま使うこと!
FULLTEXT INDEX (title, content)
) ENGINE=Mroonga
DEFAULT CHARSET=utf8mb4;
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 33

データ挿入
-- 普通に挿入するだけでよい
INSERT INTO entries
VALUES ('タイトル',
'高速に全文検索したいですね!');
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 34

全文検索
SELECT title FROM entries
WHERE -- MATCH AGAINSTで全文検索
MATCH (title, content)
-- デフォルトORがMySQLの仕様
-- 「検索」または「高速」を含むとマッチ
AGAINST ('検索 高速'
IN BOOLEAN MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 35

AND全文検索
MATCH (title, content)
-- 各キーワードの前に「+」をつけるとAND
-- 「検索」かつ「高速」を含むとマッチ
AGAINST ('+検索 +高速'
IN BOOLEAN MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 36

使いやすいAND全文検索
MATCH (title, content)
-- 最初に「*D+」をつけるとデフォルトAND
-- Mroonga独自機能
-- 「検索」かつ「高速」を含むとマッチ
AGAINST ('*D+ 検索 高速'
IN BOOLEAN MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 37

スコアー
SELECT
title,
-- ここのMATCH AGAINSTはスコアーを返す
MATCH (title, content)
AGAINST ('*D+ 検索 高速'
IN BOOLEAN MODE) AS score
FROM entries
WHERE -- ...
-- スコアーが高い順にソート
ORDER BY score DESC LIMIT 10;
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 38

ハイライト
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 39

ハイライト
SELECT mroonga_highlight_html(
title, '*D+ 検索 高速' AS query)
-- クエリーからハイライト対象のキーワードを抽出
FROM entries
WHERE
MATCH (title, content)
AGAINST ('*D+ 検索 高速' IN BOOLEAN MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 40

ハイライト結果例
<Groonga>で高速全文検索!
↓
&lt;Groonga&gt;で ← タグをエスケープ
<span class="keyword">高速</span>
全文 ↑↓キーワードはclass付け
<span class="keyword">検索</span>!
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 41

周辺テキスト
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 42

周辺テキスト
SELECT mroonga_snippet_html(
content, '*D+ 検索 高速' AS query)
-- クエリーから対象のキーワードを抽出
FROM entries
WHERE
MATCH (title, content)
AGAINST ('*D+ 検索 高速' IN BOOLEAN MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 43

周辺テキスト結果例
...<Groonga>で高速全文検索!...
↓
<div class="snippet"> ←1つ目
ga&gt;で ←タグをエスケープ
<span class="keyword">高速</span>
全文 ↑↓キーワードはclass付け
<span class="keyword">検索/span>!
</div>
<div class="snippet">...</div> ←2つ目
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 44

類似文書検索
検索クエリーは文書そのもの
キーワードではない
関連エントリーの提示に使える
メタデータがあるなら組み合わせる
→精度向上
メタデータ:タグ・行動履歴など
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 45

類似文書検索
インデックス定義
CREATE TABLE entries (
-- ...
FULLTEXT INDEX (content)
-- TokenMecabを使わないと精度がでない
-- 必要なときだけカスタマイズ!
COMMENT 'tokenizer "TokenMecab"'
) -- ...
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 46

類似文書検索
検索方法
SELECT title
FROM entries
WHERE
MATCH (content)
↓ 既存文書の内容をそのまま指定
AGAINST ('...Groongaで高速全文検索!...'
IN NATURAL LANGUAGE MODE);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 47

類似文書検索
結果例
クエリー:
...Groongaで高速全文検索!...
ヒット例:
...Mroongaで高速全文検索!...
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 48

照合順序:COLLATION
文字の並び順の規則
文字が同一かどうかの判定にも利用
適切な日本語規則なし
いわゆる
=
問題
MySQL 8では適切な日本語規則が追加される
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 49

Mroongaの照合順序
MySQL互換のもの
MySQL互換を微調整したもの
日本語でもいい感じ
Groonga提供のもの
日本語でもいい感じ
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 50

微調整した照合順序
FULLTEXT INDEX (content)
COMMENT 'normalizer "${ノーマライザー名}"'
ノーマライザー名:
NormalizerMySQLUnicode520CI
ExceptKanaCI
KanaWithVoicedSoundMark
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 51

PGroonga
(ぴーじーるんが)
PostgreSQLのインデックス
B-tree・GINなどと同じレイヤー
使用方法
CREATE INDEX ...
USING PGroonga ...
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 52

PostgreSQLの全文検索機能
textsearch(組込)
言語依存
日本語対応はメンテされていない
pg_trgm(同梱)
言語非依存:が、ほぼ日本語非対応
pg_bigm(サードパーティー)
言語非依存:日本語対応
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 53

全文検索機能:基本
AND/OR/
NOT対応
ハイライ
ト
周辺テキ
スト表示
pg_bigm
△※1 PGroonga
○
△※2 ○
△※2 ○
※1 SQLでAND/OR/NOTを組み合わせると実現可能
※2 PostgreSQLが提供する関数で実現可能。ただし、結果をHTML
で出力する用途では使えない。
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 54

全文検索機能:高度な機能
入力補完
類似文書
検索
クエリー
展開
pg_bigm
×
△※ PGroonga
○
○
× ○
※ 類似文書検索と言うよりはあいまい検索。
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 55

全文検索性能の違い
計測データ
対象:Wikipedia日本語版
レコード数:約90万件
データサイズ:約6GB
メモリー32GB・SSD500GB
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 56

検索性能1
キーワード:テレビアニメ
(ヒット数:約2万件)
pg_bigm
PGroonga:1
Groonga(参考)
Mroonga・PGroongaを使った 全文検索システムの実装方法
2.800s
0.065s
0.038s
Powered by Rabbit 2.2.1

Page: 57

検索性能2
キーワード:データベース
(ヒット数:約1万5千件)
pg_bigm
PGroonga:1
Groonga(参考)
Mroonga・PGroongaを使った 全文検索システムの実装方法
1.300s
0.049s
0.031s
Powered by Rabbit 2.2.1

Page: 58

検索性能3
キーワード:PostgreSQL OR MySQL
(ヒット数:約300件)
pg_bigm
PGroonga:1
Groonga(参考)
Mroonga・PGroongaを使った 全文検索システムの実装方法
0.049s
0.002s
0.001s
Powered by Rabbit 2.2.1

Page: 59

検索性能4
キーワード:日本
(ヒット数:約53万件)
pg_bigm:1
PGroonga
Groonga(参考)
Mroonga・PGroongaを使った 全文検索システムの実装方法
0.479s
0.563s
0.059s
Powered by Rabbit 2.2.1

Page: 60

検索性能まとめ
PGroonga:安定して速い
SQLで使えて機能豊富で速い!
pg_bigm
ヒット数が少なければ速い
キーワードが2文字以下なら速い
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 61

全文検索システムの実装
PGroonga
全文検索
キーワードハイライト
周辺テキスト表示
入力補完
関連文書の表示
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 62

全文検索
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 63

テーブル定義
CREATE TABLE entries (
-- プライマリーキーを用意する
-- スコアーでソートするために必要
id integer PRIMARY KEY,
title text,
content text
);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 64

インデックス定義
-- 全文検索用インデックス
-- よくわからないなら
-- デフォルトのまま使うこと!
CREATE INDEX entries_full_text_search
ON entries
--「USING PGroonga」=「PGroongaを使う」
USING PGroonga (id, title, content);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 65

データ挿入
-- 普通に挿入するだけでよい
INSERT INTO entries
VALUES (1,
'Groongaで高速全文検索!',
'高速に全文検索したいですね!');
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 66

全文検索
SELECT title FROM entries
WHERE
-- &@~で全文検索
-- 「検索」と「高速」をAND検索
title &@~ '検索 高速' OR
content &@~ '検索 高速';
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 67

全文検索:LIKE
SELECT title FROM entries
WHERE
-- LIKEでもインデックスが効く
--=アプリを書き換えずに高速化可能
-- ただし&@~より性能が落ちる
title LIKE '%検索%' OR
content LIKE '%検索%';
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 68

スコアー
SELECT
title,
-- pgroonga.score(テーブル名)で
-- スコアーを取得
pgroonga.score(entries) AS score
FROM entries
WHERE -- ...
-- スコアーが高い順にソート
ORDER BY score DESC LIMIT 10;
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 69

ハイライト
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 70

ハイライト
SELECT
pgroonga.highlight_html(
title,
-- クエリーから対象キーワードを抽出
pgroonga.query_extract_keywords('検索 高速'))
FROM entries
WHERE title &@~ '検索 高速' OR
content &@~ '検索 高速';
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 71

ハイライト結果例
<Groonga>で高速全文検索!
↓
&lt;Groonga&gt;で ← タグをエスケープ
<span class="keyword">高速</span>
全文 ↑↓キーワードはclass付け
<span class="keyword">検索</span>!
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 72

周辺テキスト
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 73

周辺テキスト
SELECT
pgroonga.snippet_html(
content,
-- クエリーから対象キーワードを抽出
pgroonga.query_extract_keywords('検索 高速'))
FROM entries
WHERE title &@~ '検索 高速' OR
content &@~ '検索 高速';
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 74

周辺テキスト結果例
...<Groonga>で高速全文検索!...
↓
ARRAY[
↓ 1つ目
'ga&gt;で ←タグをエスケープ
<span class="keyword">高速</span>
全文 ↑↓キーワードはclass付け
<span class="keyword">検索/span>!',
'...' ← 2つ目
]
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 75

入力補完
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 76

入力補完
実装方法
以下の検索のOR
前方一致検索
ヨミガナでの前方一致検索
緩い全文検索
表示文字列でソートして提示
https://pgroonga.github.io/ja/how-to/auto-complete.html
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 77

入力補完
テーブル定義
CREATE TABLE terms (
-- 補完候補
term text,
-- この候補のヨミガナ(N個可)
readings text[]
);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 78

入力補完
データ例
INSERT INTO terms VALUES (
'牛乳', -- 補完候補
ARRAY[
-- ヨミガナはカタカナで指定する
'ギュウニュウ',
-- 「ミルク」でも補完できるようになる
'ミルク'
]
);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 79

入力補完
データ管理のポイント
普通のテーブルなので管理が楽
追加・削除・更新が楽
ダンプ・リストアもいつも通り
レプリケーションもいつも通り
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 80

入力補完
前方一致用インデックス
CREATE INDEX prefix_search ON terms
USING PGroonga
-- ...text_term_search...
(term pgroonga.text_term_search_ops_v2,
-- ...text_array_term_search...
readings pgroonga.text_array_term_search_ops_v2);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 81

入力補完
緩い全文検索用
CREATE INDEX loose_search ON terms
USING PGroonga
-- ...text_full_text_search...
(term pgroonga.text_full_text_search_ops_v2)
-- 緩い全文検索用トークナイザー
WITH (tokenizer='TokenBigramSplitSymbolAlphaDigit');
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 82

入力補完
検索方法
SELECT term FROM terms
-- 前方一致検索
WHERE term &^ '${入力}' OR
-- ローマ字で前方一致検索
readings &^~ '${入力}' OR
-- 緩い全文検索
term &@ '${入力}'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 83

入力補完
検索例:漢字1
-- ユーザーが「牛」を入力した場合
SELECT term FROM terms
-- 前方一致検索(ヒット)
WHERE term &^ '牛' OR
-- ヨミガナで前方一致検索
readings &^~ '牛' OR
-- 緩い全文検索(ヒット)
term &@ '牛'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 84

入力補完
検索例:漢字2
-- ユーザーが「乳」を入力した場合
SELECT term FROM terms
-- 前方一致検索
WHERE term &^ '乳' OR
-- ヨミガナで前方一致検索
readings &^~ '乳' OR
-- 緩い全文検索(ヒット)
term &@ '乳'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 85

入力補完
検索例:カタカナ
-- ユーザーが「ギュウ」を入力した場合
SELECT term FROM terms
-- 前方一致検索
WHERE term &^ 'ギュウ' OR
-- ヨミガナで前方一致検索(ヒット)
readings &^~ 'ギュウ' OR
-- 緩い全文検索
term &@ 'ギュウ'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 86

入力補完
検索例:ひらがな
-- ユーザーが「ぎゅう」を入力した場合
SELECT term FROM terms
-- 前方一致検索
WHERE term &^ 'ぎゅう' OR
-- ヨミガナで前方一致検索(ヒット)
readings &^~ 'ぎゅう' OR
-- 緩い全文検索
term &@ 'ぎゅう'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 87

入力補完
検索例:ローマ字
-- ユーザーが「gyu」を入力した場合
SELECT term FROM terms
-- 前方一致検索
WHERE term &^ 'gyu' OR
-- ヨミガナで前方一致検索(ヒット)
readings &^~ 'gyu' OR
-- 緩い全文検索
term &@ 'gyu'
ORDER BY term LIMIT 10; -- ソート
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 88

同義語展開
同義語
同じ意味だが表記が異なる語
例:「刺身」と「お造り」
どの表記でもヒットして欲しい
同義語展開→同義語すべてでOR検索
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 89

同義語展開
実装方法
同義語管理テーブルを作成
クエリー内の同義語を展開
展開後のクエリーで検索
https://pgroonga.github.io/ja/reference/functions/
pgroonga-query-expand.html
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 90

同義語展開
テーブル定義
CREATE TABLE synonyms (
-- 展開対象の語
term text,
-- 同義語のリスト
-- term自身も含める
-- 含めない場合はtermが検索禁止語になる
terms text[]
);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 91

同義語展開
データ例
INSERT INTO synonyms
VALUES ('刺身', -- 「刺身」を展開
ARRAY['刺身', 'お造り']),
('お造り', -- 「お造り」を展開
ARRAY['お造り', '刺身']);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 92

同義語展開
データ管理のポイント
普通のテーブルなので管理が楽
追加・削除・更新が楽
ダンプ・リストアもいつも通り
レプリケーションもいつも通り
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 93

同義語展開
インデックス定義
CREATE INDEX synonym_search ON synonyms
USING PGroonga
-- ...text_term_search...
-- termで完全一致検索をするため
(term pgroonga.text_term_search_ops_v2);
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 94

同義語展開
確認方法
SELECT pgroonga.query_expand(
'synonyms', -- テーブル名
'term', -- 展開対象のカラム名
'terms', -- 対応する同義語配列のカラム名
'刺身' -- クエリー
);
-- '((刺身) OR (お造り))'
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 95

同義語展開
検索方法
SELECT title FROM entries
WHERE
-- title &@~ '和食 OR ((刺身) OR (お造り))'になる
title &@~
pgroonga.query_expand('synonyms',
'term',
'terms',
'和食 OR 刺身');
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 96

類似文書検索
検索クエリーは文書そのもの
キーワードではない
関連エントリーの提示に使える
メタデータがあるなら組み合わせる
→精度向上
メタデータ:タグ・行動履歴など
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 97

類似文書検索
インデックス定義
CREATE INDEX entries_similar_search
ON entries
USING PGroonga (
id,
-- pg...v2の指定がポイント
content pgroonga.text_full_text_search_ops_v2
-- TokenMecabを使うと精度向上
) WITH (tokenizer='TokenMecab');
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 98

類似文書検索
検索方法
SELECT title
FROM entries
WHERE
-- &~?で類似文書検索
-- 既存文書の内容をそのまま指定
content &~?
'...Groongaで高速全文検索!...';
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 99

類似文書検索
結果例
クエリー:
...Groongaで高速全文検索!...
ヒット例:
...PGroongaで高速全文検索!...
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 100

全文検索システムの実装
まとめ
全文検索
キーワードハイライト
周辺テキスト表示
入力補完
関連文書の表示
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 101

全文検索システムの実装
次の一歩
構造化データ対応
オフィス文書・HTMLなど
対応に必要な処理
テキスト抽出
メタデータ抽出 (例:タイトル・更新日時)
スクリーンショット作成 (なおよい)
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 102

抽出ツール
Apache Tika
Apache Luceneのサブプロジェクト
対応フォーマット数が多い
ChupaText
Groongaのサブプロジェクト
スクリーンショット作成対応
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 103

ChupaText
対応フォーマット
Word/Excel/PowerPoint
ODT/ODS/ODP (OpenDocument)
PDF/HTML/XML/CSV/...
インターフェイス
HTTPとコマンドライン
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 104

ChupaText:インストール
DockerかVagrantを使うのが楽
https://github.com/ranguba/chupa-text-docker
https://github.com/ranguba/chupa-text-vagrant
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 105

ChupaText:Docker
% GITHUB=https://github.com
% git clone \
${GITHUB}/ranguba/chupa-text-docker.git
% cd chupa-text-docker
% docker-compose up --build
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 106

ChupaText:使い方
% curl \
--form data=@XXX.pdf \
http://localhost:20080/extraction.json
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 107

ChupaText:結果例
{
"mime-type": "application/pdf", # 元データのMIMEタイプ
"size": 147159, # メタデータ
...,
"texts": [ # 抽出されたテキスト(N個)
{
"mime-type": "text/plain", # 抽出後のMIMEタイプ
...,
"creator": "Adobe Illustrator CS3", # メタデータ
"body": "This is sample PDF. ...", # 抽出したテキスト
"screenshot": {
"mime-type": "image/png", # スクリーンショットのMIMEタイプ
"data": "iVBORw...", # Base64にした画像データ
"encoding": "base64" # Base64であることを明記
}
}
]
}
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 108

ChupaText:Web UI
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 109

ChupaText:Web UI抽出例
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 110

ChupaText:Web UI抽出例
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 111

ChupaText:Vagrant
% GITHUB=https://github.com
% git clone \
${GITHUB}/ranguba/chupa-text-vagrant.git
% cd chupa-text-vagrant
% vagrant up
使い方はDocker版と同じ
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 112

ChupaText:活用例
抽出したテキスト
Mroonga・PGroongaへ挿入
抽出したメタデータ
Mroonga・PGroongaへ挿入
絞り込みに活用
作成したスクリーンショット
検索結果表示時に掲載
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 113

まとめ
RDBMS経由で全文検索エンジン
採用の判断材料を提供
全文検索システム実装例を紹介
Mroonga・PGroonga両方
構造化データの対応方法を紹介
ChupaText
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 114

扱わなかった話題
運用について
障害対策・レプリケーション
チューニング
Groongaの機能を直接使う方法
今後のセミナーの話題にするには
実例ベースの方がやりやすいので
あなたのケースを教えてください
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Page: 115

サポートサービス紹介
導入支援 (設計支援・性能検証・移行支援・…)
開発支援
(サンプルコード提供・問い合わせ対応・…)
運用支援 (障害対応・チューニング支援・…)
問い合わせ先:
https://www.clear-code.com/contact/?
type=groonga
Mroonga・PGroongaを使った 全文検索システムの実装方法
Powered by Rabbit 2.2.1

Other slides

Apache Arrow Apache Arrow
2018-12-08
Apache Arrow Apache Arrow
2018-11-17
Apache Arrow Apache Arrow
2017-06-13
Apache Arrow Apache Arrow
2017-05-28
Mroonga! Mroonga!
2015-10-30