Rabbit Slide Show

MySQL・PostgreSQLだけで作る高速あいまい全文検索システム

2018-09-20

Description

ナイーブな全文検索は単なる中間一致検索です。しかし、現実に人が入力するテキストは揺れまくっているので単なる中間一致検索では必要な情報を見つけられません。たとえば、「(090)1234-5678」も「090ー1234ー5678」も「09012345678」もすべて同じ電話番号として扱いたいのが現実です。 MySQLとPostgreSQLの全文検索機能ではこのようにゆるい全文検索を高速に実現することができません。そこでMroonga・PGroongaです。Mroonga・PGroongaを使ってMySQL・PostgreSQLだけで高速にゆるく全文検索する方法を紹介します。

Text

Page: 1

MySQL・PostgreSQLだけで作る
高速あいまい全文検索システム
須藤功平
株式会社クリアコード
db tech showcase Tokyo 2018
2018-09-20
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 2

全文検索システム
大量の文書から
指定されたキーワードを使って
高速に必要な文書を
見つけるシステム
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 3

dbts2017
MySQL・PostgreSQLだけで作る
高速でリッチな全文検索システム
須藤功平
株式会社クリアコード
db tech showcase Tokyo 2017
2017-09-07
MySQL・PostgreSQLだけで作る 高速でリッチな全文検索システム
Powered by Rabbit 2.2.1
https://slide.rabbit-shocker.org/authors/kou/db-tech-showcase-tokyo-2017/
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 4

リッチな全文検索システム
キーワードハイライト
周辺テキスト表示
入力補完・同義語展開
関連文書の表示
構造化データ対応(例:オフィス文書)
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 5

もっとリッチな全文検索システム
大量の文書から
あいまいな情報を使って
高速に必要な文書を
見つけるシステム
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 6

あいまいな情報
相手が人だから
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 7

人
文書内の表記が揺れる
例:「焼き肉」「焼きにく」
検索対象
提供情報が間違っている
例:「テノクロジー」
検索クエリー
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 8

もっとリッチな全文検索システム
大量の文書から
あいまいな情報を使って
高速に必要な文書を
見つけるシステム
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 9

ツール
全文検索エンジン
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 10

普通の全文検索エンジン
高速検索
あいまい検索
独自の使い方
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 11

開発しやすいシステム
SQLで使える
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 12

使いやすい全文検索エンジン
高速検索
あいまい検索
SQLで使える
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 13

SQLで使える全文検索エンジン
Mroonga
MySQL・MariaDB用
http://mroonga.org/ja/docs/install.html
PGroonga
PostgreSQL用
https://pgroonga.github.io/ja/install/
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 14

あいまい検索:表記ゆれ1
焼肉:全部漢字
焼き肉:送り仮名
焼きにく:まぜまぜ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 15

あいまい検索:表記ゆれ1対策
ヨミガナ検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 16

ヨミガナ検索
ヨミガナで検索
「焼肉」→「ヤキニク」
「焼きにく」→「ヤキニク」
どちらも同じになる
人名(高と髙とか)にも使える
ヨミガナ情報の取得が必要
MeCabで自動化可能
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 17

MeCabでヨミガナ化
% echo 焼肉と焼きにく | mecab | cut -d, -f8
ヤキニク
ト
ヤキニク
EOS
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 18

ヨミガナ検索:Mroonga:テーブル定義
CREATE TABLE menus (
name varchar(255),
-- 検索対象
FULLTEXT INDEX (name) -- ヨミガナ検索対応インデックス
COMMENT
'tokenizer "TokenMecab(\'use_reading\', true)"'
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 19

ヨミガナ検索:Mroonga:データ例
INSERT INTO menus
VALUES ('焼肉定食'),
('焼きにく定食');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 20

ヨミガナ検索:Mroonga:検索
SELECT name FROM menus
WHERE MATCH (name)
AGAINST ('*D+ 焼きにく' IN BOOLEAN MODE);
-- 焼肉定食
-- 焼きにく定食
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 21

ヨミガナ検索:PGroonga:テーブル定義
CREATE TABLE menus (
name text -- 検索対象
);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 22

ヨミガナ検索:PGroonga:インデックス定義
CREATE INDEX menus_search ON menus
USING PGroonga (name)
WITH (tokenizer='TokenMecab("use_reading", true)');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 23

ヨミガナ検索:PGroonga:データ例
INSERT INTO menus
VALUES ('焼肉定食'),
('焼きにく定食');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 24

ヨミガナ検索:PGroonga:検索
SELECT name FROM menus
WHERE name &@~ '焼きにく';
-- 焼肉定食
-- 焼きにく定食
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 25

あいまい検索:表記ゆれ2
「ぼたん鍋」
と
「猪鍋」
(別名)
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 26

あいまい検索:表記ゆれ2対策
同義語展開
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 27

同義語展開
実行前にクエリーを変換
「ぼたん鍋」→「ぼたん鍋 OR 猪鍋」
どちらもヒット
変換ルールは事前に用意
ある程度自動生成可能
例:NEologdやWikipediaを利用
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 28

同義語展開:Mroonga:テーブル定義
CREATE TABLE synonyms (
term varchar(255),
-- 展開対象の語
synonym varchar(255), -- 同義語
INDEX (term)
-- 高速化と精度向上
COMMENT 'normalizer "NormalizerNFKC100"'
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 29

同義語展開:Mroonga:データ例
INSERT INTO synonyms
-- 「ぼたん鍋」を「ぼたん鍋 OR 猪鍋」に展開
VALUES ('ぼたん鍋', 'ぼたん鍋'),
('ぼたん鍋', '猪鍋'),
-- 「猪鍋」を「猪鍋 OR ぼたん鍋」に展開
('猪鍋', '猪鍋'),
('猪鍋', 'ぼたん鍋');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 30

同義語展開:Mroonga:確認方法
SELECT mroonga_query_expand(
'synonyms',
-- テーブル名
'term',
-- 展開対象のカラム名
'synonym',
-- 対応する同義語のカラム名
'ランチ ぼたん鍋' -- クエリー
);
-- 'ランチ ((ぼたん鍋) OR (猪鍋))'
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 31

同義語展開:Mroonga:検索方法
SELECT title FROM entries
WHERE
MATCH (title)
-- '*D+ ランチ OR ((ぼたん鍋) OR (猪鍋))'になる
AGAINST (mroonga_query_expand('synonyms',
'term',
'synonym',
'*D+ ランチ ぼたん鍋')
IN BOOLEAN MODE);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 32

同義語展開:PGroonga:テーブル定義
CREATE TABLE synonyms (
-- 展開対象の語
term text,
-- 同義語のリスト
-- term自身も含める
-- 含めない場合はtermが検索禁止語になる
terms text[]
);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 33

同義語展開:PGroonga:データ例
INSERT INTO synonyms
VALUES ('ぼたん鍋', -- 「ぼたん鍋」を展開
ARRAY['ぼたん鍋', '猪鍋']),
('猪鍋', -- 「猪鍋」を展開
ARRAY['猪鍋', 'ぼたん鍋']);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 34

同義語展開:PGroonga:インデックス定義
CREATE INDEX synonym_search ON synonyms
USING PGroonga
-- ...text_term_search...
-- termで完全一致検索をするため
(term pgroonga_text_term_search_ops_v2);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 35

同義語展開:PGroonga:確認方法
SELECT pgroonga_query_expand(
'synonyms', -- テーブル名
'term', -- 展開対象のカラム名
'terms', -- 対応する同義語配列のカラム名
'ランチ ぼたん鍋' -- クエリー
);
-- 'ランチ ((ぼたん鍋) OR (猪鍋))'
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 36

同義語展開:PGroonga:検索方法
SELECT title FROM entries
WHERE
-- title &@~ ランチ ((ぼたん鍋) OR (猪鍋))'になる
title &@~
pgroonga_query_expand('synonyms',
'term',
'terms',
'ランチ ぼたん鍋');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 37

あいまい検索:表記ゆれ3
090-1234-5678:ハイフン入り
(090)1234-5678:カッコとハイフン入り
09012345678:区切りなし
090 1234 5678:空白区切り
(090)1234ー5678:全角文字入り
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 38

あいまい検索:表記ゆれ3対策
電話番号検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 39

電話番号検索
文字を正規化
全角→半角
ハイフンっぽい文字→ハイフン
長音っぽい文字→ハイフン
記号・空白を無視して検索
元クエリー:(090)1234 5678
実クエリー:09012345678
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 40

電話番号検索:Mroonga:テーブル定義
CREATE TABLE people (
tel varchar(255), -- 検索対象
FULLTEXT INDEX (tel) COMMENT
-- 電話番号検索対応インデックス
'normalizer "NormalizerNFKC100(
\'unify_hyphen_and_prolonged_sound_mark\', true)",
tokenizer "TokenNgram(\'loose_symbol\', true,
\'loose_blank\', true)"'
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 41

電話番号検索:Mroonga:データ例
INSERT INTO people
VALUES ('090-1234-5678'),
('(090)1234-5678'),
('09012345678'),
('090 1234 5678'),
('(090)1234ー5678');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 42

電話番号検索:Mroonga:検索
SELECT tel FROM people
WHERE MATCH (tel)
AGAINST ('*D+ 090ー12345678' IN BOOLEAN MODE);
-- 090-1234-5678
-- (090)1234-5678
-- 09012345678
-- 090 1234 5678
-- (090)1234ー5678
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 43

電話番号検索:PGroonga:テーブル定義
CREATE TABLE people (
tel text -- 検索対象
);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 44

電話番号検索:PGroonga:インデックス定義
CREATE INDEX people_search ON people
USING PGroonga (tel)
WITH (normalizer='
NormalizerNFKC100("unify_hyphen_and_prolonged_sound_mark", true)',
tokenizer='TokenNgram("loose_symbol", true,
"loose_blank", true)');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 45

電話番号検索:PGroonga:データ例
INSERT INTO people
VALUES ('090-1234-5678'),
('(090)1234-5678'),
('09012345678'),
('090 1234 5678'),
('(090)1234ー5678');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 46

電話番号検索:PGroonga:検索
SELECT tel FROM people
WHERE tel &@~ '090ー12345678';
-- 090-1234-5678
-- (090)1234-5678
-- 09012345678
-- 090 1234 5678
-- (090)1234ー5678
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 47

あいまい検索:表記ゆれ4
sèvre-et-maine
セーヴェル エ メーヌ
「ーヴェ」・空白区切り
セブルエメーヌ
「ブ」・区切りなし
セーブル・エ・メーヌ
「ーブ」・中点区切り
セーヴル
エメーヌ
「ーヴ」・片方だけ空白区切り
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 48

あいまい検索:表記ゆれ4対策
ワイン名検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 49

ワイン名検索
文字を正規化
ヴ・ヴェ→ブ
ハイフン・長音っぽい文字→ハイフン
中点っぽい文字→中点
記号・空白を無視して検索
元クエリー:セーヴェル・エメーヌ
実クエリー:セブルエメヌ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 50

ワイン名検索:Mroonga:テーブル定義
CREATE TABLE wines (
name varchar(255), -- 検索対象
FULLTEXT INDEX (name) COMMENT
-- ワイン名検索対応インデックス
'normalizer "NormalizerNFKC100(
\'unify_katakana_bu_sound\', true,
\'unify_hyphen_and_prolonged_sound_mark\', true,
\'unify_middle_dot\', true)",
tokenizer "TokenNgram(\'loose_symbol\', true,
\'loose_blank\', true)"'
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 51

ワイン名検索:Mroonga:データ例
INSERT INTO wines
VALUES ('セーヴェル エ メーヌ'),
('セブルエメーヌ'),
('セーブル・エ・メーヌ'),
('セーヴル エメーヌ');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 52

ワイン名検索:Mroonga:検索
SELECT name FROM wines
WHERE MATCH (name)
AGAINST ('*D+ セーヴェルエメーヌ' IN BOOLEAN MODE);
-- セーヴェル エ メーヌ
-- セブルエメーヌ
-- セーブル・エ・メーヌ
-- セーヴル エメーヌ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 53

ワイン名検索:PGroonga:テーブル定義
CREATE TABLE wines (
name text -- 検索対象
);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 54

ワイン名検索:PGroonga:インデックス定義
CREATE INDEX wines_search ON wines
USING PGroonga (name)
WITH (normalizer='NormalizerNFKC100(
"unify_katakana_bu_sound", true,
"unify_hyphen_and_prolonged_sound_mark", true,
"unify_middle_dot", true)',
tokenizer='TokenNgram("loose_symbol", true,
"loose_blank", true)');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 55

ワイン名検索:PGroonga:データ例
INSERT INTO wines
VALUES ('セーヴェル エ メーヌ'),
('セブルエメーヌ'),
('セーブル・エ・メーヌ'),
('セーヴル エメーヌ');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 56

ワイン名検索:PGroonga:検索
SELECT name FROM wines
WHERE name &@~ 'セーヴェルエメーヌ';
-- セーヴェル エ メーヌ
-- セブルエメーヌ
-- セーブル・エ・メーヌ
-- セーヴル エメーヌ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 57

表記ゆれ:まとめ
ヨミガナ検索
漢字・送り仮名の違いを吸収
同義語展開:別名をカバー
電話番号検索
半角全角・記号の有無・記号の違いを吸収
ワイン名検索
外来語のカタカナ表記の違いを吸収
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 58

表記ゆれ:参考情報
文字の正規化方法
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 59

正規化:かなの同一視
unify_kana
ひらがなとカタカナを区別しない
↓は同じ
あいうえお
アイウエオ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 60

正規化:濁点の同一視
unify_sound_mark
濁点・半濁点の有無を区別しない
↓は同じ
はひふへほ
ばびぶべぼ
ぱぴぷぺぽ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 61

正規化:大文字・小文字の同一視
unify_kana_case
大文字・小文字を区別しない
↓は同じ
やゆよ
ゃゅょ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 62

正規化:ハイフンっぽい文字の同一視
unify_hyphen
ハイフンっぽい文字をハイフンへ
ハイフン:U+002D
ハイフンっぽい文字:
-˗֊‐‑‒–⁃⁻₋−
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 63

正規化:長音記号っぽい文字の同一視
unify_prolonged_sound_mark
長音記号っぽい文字を長音記号へ
長音記号:U+30FC
長音記号っぽい文字:
ー—―─━ー
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 64

正規化:ハイフン・長音記号っぽい文字
unify_hyphen_and_prolonged_sound_mark
ハイフン・長音記号っぽい文字を
ハイフン(U+002D)へ
ハイフンっぽい文字:
-˗֊‐‑‒–⁃⁻₋−
長音記号っぽい文字:
ー—―─━ー
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 65

正規化:中点っぽい文字の同一視
unify_middle_dot
中点っぽい文字を中点へ
中点:U+00B7
中点っぽい文字
·ᐧ•∙⋅⸱・・
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 66

正規化:ヴァ→バ
unify_katakana_v_sounds
ヴァ行をバ行へ
↓は同じ
ヴァヴィヴヴェヴォ
バビブベボ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 67

正規化:ヴァ行→ブ
unify_katakana_bu_sound
ヴァ行をブへ
↓は同じ
ヴァヴィヴヴェヴォ
ブブブブブ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 68

正規化:MySQL 8.0
日本語用COLLATIONを追加
utf8mb4_ja_0900_as_cs
COLLATION:文字の順序のルール
順序なので等価比較機能もある
最新Mroongaは対応済み
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 69

正規化:PostgreSQL 10
ICUベースのCOLLATION対応
ICU:Unicode処理ライブラリー
COLLATION:文字の順序のルール
順序なので等価比較機能もある
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 70

あいまい検索:typo
テノクロジー
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 71

あいまい検索:typo対策
fuzzy検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 72

fuzzy検索
似ている文字列を検索
似ている=編集距離が小さい
インデックスを使って検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 73

編集距離
Aを何回編集するとBになるか
編集:
挿入・削除・置換
置換を禁止するケースもある
編集回数が距離
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 74

編集距離例:置換あり
A:テノクロジー
置換:ク↔ノ
B:テクノロジー
編集距離:1
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 75

編集距離例:置換なし
A:テノクロジー
削除:ク:テノロジー
挿入:ノ:テクノロジー
B:テクノロジー
編集距離:2
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 76

fuzzy検索:Mroonga:テーブル定義
CREATE TABLE tags (
name varchar(255),
-- 検索対象
FULLTEXT INDEX (name) -- fuzzy検索対応インデックス
COMMENT 'tokenizer "none"'
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 77

fuzzy検索:Mroonga:データ例
INSERT INTO tags
VALUES ('テクノロジー'),
('テクニカル');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 78

fuzzy検索:Mroonga:検索
SELECT name,
MATCH(name) AGAINST(...↓と同じ内容...) AS score
FROM tags
WHERE MATCH (name)
AGAINST (CONCAT('*SS fuzzy_search(name, ',
mroonga_escape('テノクロジー' AS script),
', ',
'{"with_transposition": true,
"max_distance": 4})')
IN BOOLEAN MODE);
-- テクノロジー | 4
-- テクニカル | 1
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 79

fuzzy検索:PGroonga:テーブル定義
CREATE TABLE tags (
name text -- 検索対象
);
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 80

fuzzy検索:PGroonga:インデックス定義
CREATE INDEX tags_search ON tags
USING PGroonga (name)
WITH (tokenizer='');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 81

fuzzy検索:PGroonga:データ例
INSERT INTO tags
VALUES ('テクノロジー'),
('テクニカル');
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 82

fuzzy検索:PGroonga:検索
SELECT name, pgroonga_score(tableoid, ctid)
FROM tags
WHERE name &`
('fuzzy_search(name, ' ||
pgroonga_escape('テノクロジー') || ',
{"with_transposition": true,
"max_distance": 4})');
-- テクノロジー | 4
-- テクニカル | 1
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 83

まとめ:あいまいな情報
人が用意した情報はあいまい
クエリーも検索対象も
あいまいでも必要な文書を見つける
人よりも機械ががんばる
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 84

まとめ:あいまいな検索
全文検索エンジンを活用して実現
あいまい検索機能を提供しているはず
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 85

まとめ:全文検索エンジン
普通の全文検索エンジン
独自の使い方
Mroonga・PGroonga
SQLで使える→開発しやすい
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 86

まとめ:ヨミガナ検索
漢字・送り仮名の違いを吸収
焼肉・焼き肉・焼きにく
高橋・髙橋
MeCabで自動化できる
辞書により失敗することはある
同義語には対応できない
同義語展開と併用
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 87

まとめ:同義語展開
別名に対応:「ぼたん鍋」と「猪鍋」
なにを同義語とするかが難しい
システム依存度が高い
ある程度は自動化できる
手動でのメンテナンスも必要
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 88

まとめ:電話番号検索
半角全角・記号有無・記号違いを吸収
注意
どんな検索対象でもゆるくてよいわけではない
誤ヒットも増えてしまう
電話番号ならここまでゆるくてもOKというだけ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 89

まとめ:ワイン名検索
外来語のカタカナ表記の違いを吸収
注意
どんな検索対象でもゆるくてよいわけではない
誤ヒットも増えてしまう
ワイン名ならここまでゆるくてもOKというだけ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 90

補足:ゆるくするなら重みも考慮
検索対象を限定できないがゆるくしたい
ゆるくない検索と組み合わせて重み調整
ゆるくない方がゆるい方より重要
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 91

重み調整例:Mroonga
SELECT
MATCH(...) AGAINST(...ゆるくない...) * 10 +
MATCH(...) AGAINST(...ゆるい...) AS score
...;
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 92

重み調整例:PGroonga
SELECT pgroonga_score(tableoid, ctid)
WHERE
... &@~ ('...ゆるくない...',
ARRAY[10],
'pgroonga_index')::pgroonga_full_text_search_condition OR
... &@~ '...ゆるい....';
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 93

まとめ:fuzzy検索
typoしても本来のキーワードを推測
活用方法:
ヒットしなかったときの「もしかして」の実装
入力補完候補
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 94

参考情報:リッチな全文検索システム
MySQL・PostgreSQLだけで作る
高速でリッチな全文検索システム
須藤功平
株式会社クリアコード
db tech showcase Tokyo 2017
2017-09-07
MySQL・PostgreSQLだけで作る 高速でリッチな全文検索システム
Powered by Rabbit 2.2.1
https://slide.rabbit-shocker.org/authors/kou/db-tech-showcase-tokyo-2017/
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 95

扱わなかったあいまい検索1
近傍検索
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 96

近傍検索
指定したキーワード間に
違う単語が含まれていてもマッチ
「みそラーメン」で検索:
「みそバターラーメン」:マッチ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 97

扱わなかったあいまい検索2
quorumマッチ
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 98

quorumマッチ
閾値以上の要素がマッチしたらマッチ
閾値2と
「MySQL MariaDB Percona」で検索:
「MySQLとMariaDBの比較」:マッチ
「MySQLとPostgreSQLの比較」:マッチしない
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 99

扱わなかった話題
運用について
障害対策・レプリケーション
チューニング
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Page: 100

サポートサービス紹介
導入支援 (設計支援・性能検証・移行支援・…)
開発支援 (サンプルコード提供・問い合わせ対応・…)
運用支援 (障害対応・チューニング支援・…)
問い合わせ先:
https://www.clear-code.com/contact/?type=groonga
MySQL・PostgreSQLだけで作る 高速あいまい全文検索システム
Powered by Rabbit 2.2.2

Other slides

Apache Arrow Apache Arrow
2017-06-13
Apache Arrow Apache Arrow
2017-05-28
Mroonga! Mroonga!
2015-10-30