rabbit-slide-komainu8-postgresql-conference-japan-2021 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c70ecfa7c7eba2672af560d513cd242a2dbcf99d1705a25276c6dde7a46bd689
4
+ data.tar.gz: 9e126bdb80ea9514826a2df952da77885659f39b093dae75eb90780ac924be39
5
+ SHA512:
6
+ metadata.gz: 5f36961f4d290ab89fe04eadbe7cd8abc03bc0c29b5340ede122ffb465261bf63e53b671be11757a9dda8b5b32a6cf84dd3ef156f0cd495dd5a3310595b1f4bc
7
+ data.tar.gz: b3c6839c4421c6bdf559e2ebeb46bd0de10a878f6a5bb3aed0478e9029703d6234fdb27b77587aea1501d85fbe0ebc53ad1ae74e22746519c9acf9bfccb2f783
data/.rabbit ADDED
@@ -0,0 +1 @@
1
+ improve-search-result-with-pgroonga.rab
data/README.rd ADDED
@@ -0,0 +1,42 @@
1
+ = PGroongaを使って全文検索結果をより良くする方法
2
+
3
+ PostgreSQL で使用できる全文検索の拡張に PGroonga という高速に全文検索できる拡張があります。
4
+
5
+ PGroongaはバックエンドに本格的な全文検索エンジンGroongaを使っており、高速な全文検索以外にも、
6
+ より良い検索結果を出すための機能(検索結果の適合率や再現率の向上や、より良い結果順にするためのスコアリング)
7
+ が盛り込まれています。
8
+
9
+ PGroongaはPostgreSQLの拡張なので、SQLベースでこれらの機能を使うことができ、
10
+ SQLを使い慣れている人であれば、比較的スムーズにこれらの機能を使えます。
11
+
12
+ 本発表では、全文検索結果をより良くするPGroongaの機能について、どのような機能があり、
13
+ それらをどう使うのかについて網羅的に紹介します。
14
+
15
+ == ライセンス
16
+
17
+ === スライド
18
+
19
+ CC BY-SA 4.0
20
+
21
+ 原著作者:堀本泰弘
22
+
23
+ == 作者向け
24
+
25
+ === 表示
26
+
27
+ rake
28
+
29
+ === 公開
30
+
31
+ rake publish
32
+
33
+ == 閲覧者向け
34
+
35
+ === インストール
36
+
37
+ gem install rabbit-slide--postgresql-conference-japan-2021
38
+
39
+ === 表示
40
+
41
+ rabbit rabbit-slide--postgresql-conference-japan-2021.gem
42
+
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "rabbit/task/slide"
2
+
3
+ # Edit ./config.yaml to customize meta data
4
+
5
+ spec = nil
6
+ Rabbit::Task::Slide.new do |task|
7
+ spec = task.spec
8
+ # spec.files += Dir.glob("doc/**/*.*")
9
+ # spec.files -= Dir.glob("private/**/*.*")
10
+ # spec.add_runtime_dependency("rabbit-theme-YOUR-THEME")
11
+ end
12
+
13
+ desc "Tag #{spec.version}"
14
+ task :tag do
15
+ sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
16
+ sh("git", "push", "--tags")
17
+ end
data/config.yaml ADDED
@@ -0,0 +1,31 @@
1
+ ---
2
+ id: postgresql-conference-japan-2021
3
+ base_name: improve-search-result-with-pgroonga
4
+ tags: [
5
+ rabbit,
6
+ postgresql,
7
+ pgcon21j,
8
+ fts,
9
+ search,
10
+ pgroonga,
11
+ groonga
12
+ ]
13
+ presentation_date: 2021-11-12
14
+ presentation_start_time: 2021-11-12T16:10:00+09:00
15
+ presentation_end_time: 2021-11-12T17:00:00+09:00
16
+ version: 1.0.0
17
+ licenses: [
18
+ CC-BY-SA-4.0
19
+ ]
20
+ slideshare_id:
21
+ speaker_deck_id:
22
+ ustream_id:
23
+ vimeo_id:
24
+ youtube_id:
25
+ author:
26
+ markup_language: :rd
27
+ name: Horimoto Yasuhiro
28
+ email: horimoto@clear-code.com
29
+ rubygems_user: komainu8
30
+ slideshare_user:
31
+ speaker_deck_user:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,520 @@
1
+ = PGroongaを使って\n全文検索結果を\nより良くする方法
2
+
3
+ : author
4
+ 堀本 泰弘
5
+ : institution
6
+ 株式会社クリアコード
7
+ : content-source
8
+ PostgreSQL Conference Japan 2021
9
+ : date
10
+ 2021-11-12
11
+ : allotted-time
12
+ 45m
13
+ : start-time
14
+ 2021-11-12T16:10:00+09:00
15
+ : end-time
16
+ 2021-11-12T16:55:00+09:00
17
+ : theme
18
+ .
19
+
20
+ = 本日の資料
21
+
22
+ * 本日のスライド
23
+ * ((<URL:https://slide.rabbit-shocker.org/authors/komainu8/improve-search-result-with-pgroonga.rab>))
24
+
25
+ = 自己紹介
26
+
27
+ # image
28
+ # src = images/self-introduction.png
29
+ # relative_height = 107
30
+
31
+ = 目次
32
+
33
+ (1) 検索の評価指標
34
+ (2) PGroongaで検索結果の改善
35
+ (3) 参考資料
36
+
37
+ = 検索の評価指標
38
+
39
+ よく検索結果が\n
40
+ ((*いまいち*))だ...\n
41
+ という話を\n聞きます
42
+
43
+ = 検索の評価指標
44
+
45
+ # image
46
+ # src = images/search-result-01.png
47
+ # relative_height = 100
48
+
49
+ = 検索の評価指標
50
+
51
+ * 😞検索漏れ
52
+ * 😞ノイズが多い
53
+ * 😞有用な情報を探し出せない
54
+
55
+ = 検索の評価指標
56
+
57
+ (1) 効率性\n低コストで検索できるかどうか
58
+ (2) ((*有効性*))\n検索結果の全体 or 一部が\n((*欲しい情報*))だったかどうか
59
+
60
+ = 検索の評価指標
61
+
62
+ 今日は有効性に\nついてのお話です
63
+
64
+ = 有効性の指標
65
+
66
+ (1) 適合率
67
+ (2) 再現率
68
+ (3) ランキング
69
+
70
+ = 適合率と再現率
71
+
72
+ # image
73
+ # src = images/precision-recall-1.png
74
+ # relative_height = 82
75
+
76
+ = 適合率と再現率
77
+
78
+ # image
79
+ # src = images/precision-hight-recall-low.png
80
+ # relative_height = 90
81
+
82
+ = 適合率と再現率
83
+
84
+ # image
85
+ # src = images/precision-low-recall-hight.png
86
+ # relative_height = 90
87
+
88
+ = ランキング
89
+
90
+ 欲しい情報が\nランキング((*上位*))にあるか
91
+
92
+ = ランキング
93
+
94
+ ユーザーは\n((*上位数件*))\nしか見ない
95
+
96
+ = PGroongaで検索結果の改善
97
+
98
+ * PGroongaで適合率/再現率改善
99
+
100
+ * ノーマライザーを使う
101
+ * トークナイザーを使う
102
+ * ステミングを使う
103
+ * fuzzy検索を使う
104
+ * 同義語展開を使う
105
+
106
+ = PGroongaで検索結果の改善
107
+
108
+ * PGroongaでランキング改善
109
+
110
+ * スコアラーを使う
111
+
112
+ = PGroongaのノーマライザー\n(デフォルト)
113
+
114
+ # coderay sql
115
+
116
+ CREATE DATABASE pgroonga_test;
117
+ CREATE EXTENSION pgroonga;
118
+ CREATE TABLE normalizer_test (
119
+ id integer,
120
+ content text
121
+ );
122
+ CREATE INDEX pgroonga_content_index ON normalizer_test USING pgroonga (content);
123
+
124
+ INSERT INTO normalizer_test VALUES (1, 'キログラム');
125
+ INSERT INTO normalizer_test VALUES (2, 'きろぐらむ');
126
+ INSERT INTO normalizer_test VALUES (3, '㌕');
127
+ INSERT INTO normalizer_test VALUES (4, 'キログラム');
128
+ INSERT INTO normalizer_test VALUES (5, 'kiroguramu');
129
+ INSERT INTO normalizer_test VALUES (6, 'kiroguramu');
130
+
131
+ SELECT * FROM normalizer_test WHERE content &@ 'キログラム';
132
+
133
+ = PGroongaのノーマライザー\n(デフォルト)
134
+
135
+ # RT
136
+ delimiter = [|]
137
+
138
+ id | content
139
+
140
+ 1 | キログラム
141
+ 3 | ㌕
142
+ 4 | キログラム
143
+
144
+ = PGroongaのノーマライザー\n(デフォルト)
145
+
146
+ * 半角/全角を同一視
147
+ * ㌕とキログラムを同一視
148
+
149
+ = PGroongaのノーマライザー\n(デフォルト)
150
+
151
+ PGroongaのデフォルトはNFKCを使った正規化\n
152
+ ※対象のテキストのエンコードがUTF-8の時
153
+
154
+ = ノーマライザーの変更
155
+
156
+ 再現率を上げたい
157
+
158
+ = PGroongaのノーマライザー\n(NormalizerNFKC130)
159
+
160
+ # coderay sql
161
+
162
+ DROP INDEX pgroonga_content_index;
163
+ CREATE INDEX pgroonga_content_index
164
+ ON normalizer_test
165
+ USING pgroonga (content)
166
+ WITH (normalizers='NormalizerNFKC130("unify_to_romaji", true)');
167
+ SELECT * FROM normalizer_test WHERE content &@ 'キログラム';
168
+
169
+ = PGroongaのノーマライザー\n(NormalizerNFKC130)
170
+
171
+ # RT
172
+ delimiter = [|]
173
+
174
+ id | content
175
+
176
+ 1 | キログラム
177
+ 2 | きろぐらむ
178
+ 3 | ㌕
179
+ 4 | キログラム
180
+
181
+ = PGroongaのノーマライザー\n(NormalizerNFKC130)
182
+
183
+ # RT
184
+ delimiter = [|]
185
+
186
+ id | content
187
+
188
+ 5 | kiroguramu
189
+ 6 | kiroguramu
190
+
191
+ = PGroongaのノーマライザー\n(NormalizerNFKC130)
192
+
193
+ * Unify_to_romaji
194
+
195
+ * ローマ字に正規化\nローマ字で読んだときに同じ語は同一視する
196
+ * (e.g. 「kiroguramu」と「きろぐらむ」を同一視。ローマ字読みが同じだから)
197
+
198
+ = オプションの指定方法
199
+
200
+ * 'NormalizerNFKC130\n("オプション名", true)');
201
+
202
+ = 指定可能オプション一覧
203
+
204
+ * NormalizerNFKC130の\nオプション一覧
205
+ * ((<URL:https://groonga.org/ja/docs/reference/normalizers/normalizer_nfkc130.html#syntax>))
206
+
207
+ = PGroongaのトークナイザー\n(デフォルト)
208
+
209
+ # coderay sql
210
+
211
+ CREATE TABLE tokenizer_test (
212
+ title text
213
+ );
214
+ CREATE INDEX pgroonga_content_index ON tokenizer_test USING pgroonga (title);
215
+
216
+ INSERT INTO tokenizer_test VALUES ('京都府 1日目 金閣寺');
217
+ INSERT INTO tokenizer_test VALUES ('京都府 2日目 嵐山');
218
+ INSERT INTO tokenizer_test VALUES ('京都府 3日目 天橋立');
219
+ INSERT INTO tokenizer_test VALUES ('東京都 1日目 スカイツリー');
220
+ INSERT INTO tokenizer_test VALUES ('東京都 2日目 浅草寺');
221
+ INSERT INTO tokenizer_test VALUES ('北海道 1日目 函館');
222
+ INSERT INTO tokenizer_test VALUES ('北海道 2日目 トマム');
223
+ INSERT INTO tokenizer_test VALUES ('北海道 3日目 富良野');
224
+ INSERT INTO tokenizer_test VALUES ('北海道 4日目 美瑛');
225
+ INSERT INTO tokenizer_test VALUES ('北海道 5日目 旭川');
226
+
227
+ SELECT * FROM tokenizer_test WHERE title &@ '京都';
228
+
229
+ = PGroongaのトークナイザー\n(デフォルト)
230
+
231
+ # RT
232
+ delimiter = [|]
233
+
234
+ title
235
+
236
+ 京都府 1日目 金閣寺
237
+ 京都府 2日目 嵐山
238
+ 京都府 3日目 天橋立
239
+ 東京都 1日目 スカイツリー
240
+ 東京都 2日目 浅草寺
241
+
242
+ = トークナイザーの変更
243
+
244
+ 適合率を上げたい
245
+
246
+ = PGroongaのトークナイザー\n(TokenMecab)
247
+
248
+ # coderay sql
249
+
250
+ DROP INDEX pgroonga_content_index;
251
+ CREATE INDEX pgroonga_content_index
252
+ ON tokenizer_test
253
+ USING pgroonga (title)
254
+ WITH (tokenizer='TokenMecab');
255
+
256
+ SELECT * FROM tokenizer_test WHERE title &@ '京都';
257
+
258
+ = PGroongaのトークナイザー\n(TokenMecab)
259
+
260
+ # RT
261
+ delimiter = [|]
262
+
263
+ title
264
+
265
+ 京都府 1日目 金閣寺
266
+ 京都府 2日目 嵐山
267
+ 京都府 3日目 天橋立
268
+
269
+ = トークナイザーの指定方法
270
+
271
+ * tokenizer='トークナイザー名'
272
+
273
+ = 指定可能トークナイザー一覧
274
+
275
+ * 使用可能なトークナイザー
276
+ * ((<URL:https://groonga.org/ja/docs/reference/tokenizers.html>))
277
+
278
+ = ステミング(語幹処理)
279
+
280
+ 語形変化\n意味は同じだが\n語の形が変わる
281
+
282
+ = ステミング(語幹処理)
283
+
284
+ 例えば
285
+
286
+ * develop(原形)
287
+ * developped(過去形)
288
+ * developing(進行形)
289
+
290
+ 意味は同じだが語形は異なる
291
+
292
+ = ステミング(語幹処理)
293
+
294
+ 語幹:単語の変化しない部分
295
+
296
+ = ステミング(語幹処理)
297
+
298
+ (('tag:left'))
299
+ ((*develop*))\n
300
+ ((*develop*))ped\n
301
+ ((*develop*))ing
302
+
303
+ = ステミング(語幹処理)
304
+
305
+ 語幹で検索\n
306
+ ->語形変化後の語も検索できる
307
+
308
+ = PGroongaのステミング\n(未使用)
309
+
310
+ # coderay sql
311
+
312
+ CREATE TABLE steming_test (
313
+ title text
314
+ );
315
+ CREATE INDEX pgroonga_content_index ON steming_test USING pgroonga (title);
316
+
317
+ INSERT INTO tokenizer_test VALUES ('I develop Groonga');
318
+ INSERT INTO tokenizer_test VALUES ('I am developing Groonga');
319
+ INSERT INTO tokenizer_test VALUES ('I developed Groonga');
320
+
321
+ SELECT * FROM tokenizer_test WHERE title &@ 'develop';
322
+
323
+ = PGroongaのステミング\n(未使用)
324
+
325
+ # RT
326
+ delimiter = [|]
327
+
328
+ title
329
+
330
+ I develop Groonga
331
+
332
+ = PGroongaのステミング
333
+
334
+ # coderay sql
335
+
336
+ CREATE INDEX pgroonga_content_index
337
+ ON steming_test
338
+ USING pgroonga (title)
339
+ WITH (plugins='token_filters/stem',
340
+ token_filters='TokenFilterStem');
341
+
342
+ = PGroongaのステミング
343
+
344
+ # RT
345
+ delimiter = [|]
346
+
347
+ title
348
+
349
+ I develop Groonga
350
+ I am developing Groonga
351
+ I developed Groonga
352
+
353
+ = 同義語
354
+
355
+ 同義語:同じ意味を持つ別の語
356
+
357
+ = 同義語
358
+
359
+ 例えば\n
360
+ 「ミルク」と\n「牛乳」
361
+
362
+ = 同義語
363
+
364
+ 意味が同じものはヒットしてほしい
365
+
366
+ = 同義語展開
367
+
368
+ ミルク -> \n
369
+ ミルク OR 牛乳
370
+
371
+ = PGroongaの同義語展開
372
+
373
+ # coderay sql
374
+
375
+ CREATE TABLE synonyms (
376
+ term text PRIMARY KEY,
377
+ synonyms text[]
378
+ );
379
+
380
+ CREATE INDEX synonyms_search ON synonyms USING pgroonga (term pgroonga.text_term_search_ops_v2);
381
+
382
+ INSERT INTO synonyms (term, synonyms) VALUES ('ミルク', ARRAY['ミルク', '牛乳']);
383
+ INSERT INTO synonyms (term, synonyms) VALUES ('牛乳', ARRAY['牛乳', 'ミルク']);
384
+
385
+ CREATE TABLE memos (
386
+ id integer,
387
+ content text
388
+ );
389
+
390
+ INSERT INTO memos VALUES (1, '牛乳石鹸');
391
+ INSERT INTO memos VALUES (2, 'ミルクジャム');
392
+ INSERT INTO memos VALUES (3, 'ストロベリー');
393
+
394
+ CREATE INDEX pgroonga_content_index ON memos USING pgroonga (content);
395
+
396
+ SELECT * FROM memos
397
+ WHERE
398
+ content &@~
399
+ pgroonga_query_expand('synonyms', 'term', 'synonyms', '牛乳');
400
+
401
+ = 同義語展開
402
+
403
+ # RT
404
+ delimiter = [|]
405
+
406
+ id | content
407
+
408
+ 1 | 牛乳石鹸
409
+ 2 | ミルクジャム
410
+
411
+ = 曖昧検索
412
+
413
+ typo対策
414
+
415
+ = 曖昧検索
416
+
417
+ * 似たような語ならヒットする
418
+ (完全一致じゃなくてもヒットする)
419
+
420
+ = 曖昧検索
421
+
422
+ 「テノクロジー」で\n
423
+ 「テクノロジー」がヒット
424
+
425
+ = PGroongaのfuzzy検索
426
+
427
+ # coderay sql
428
+
429
+ CREATE TABLE tags (
430
+ name text
431
+ );
432
+
433
+ CREATE INDEX tags_search ON tags USING pgroonga(name) WITH (tokenizer='');
434
+ INSERT INTO tags VALUES ('テクノロジー');
435
+ INSERT INTO tags VALUES ('テクニカル');
436
+
437
+ SELECT name FROM tags
438
+ WHERE
439
+ name &`
440
+ ('fuzzy_search(name, ' || pgroonga_escape('テノクロジー') || ',
441
+ {"with_transposition": true,
442
+ "max_distance": 1})');
443
+
444
+ = 曖昧検索
445
+
446
+ # RT
447
+ delimiter = [|]
448
+
449
+ name
450
+
451
+ テクノロジー
452
+
453
+ = PGroongaでランキング改善
454
+
455
+ 何を基準に\nランキングを\n決めるのか
456
+
457
+ = PGroongaのスコアリング
458
+
459
+ * TF(PGroongaのデフォルト)
460
+ * TF-IDF
461
+
462
+ = PGroongaのスコアリング\nTF(デフォルト)
463
+
464
+ 単語の((*出現数*))\nが大事
465
+
466
+ = PGroongaのスコアリング\nTF(デフォルト)
467
+
468
+ * 検索キーワードが文書内に多く含まれる文書のスコアーが高くなる
469
+
470
+ = PGroongaのスコアリング\nTF-IDF
471
+
472
+ 単語の((*レア度*))\nが大事
473
+
474
+ = PGroongaのスコアリング\nTF-IDF
475
+
476
+ * 文書に出てくる頻度が高い\n(レア度低い)
477
+ * 文書に出てくる頻度が低い\n(レア度高い)
478
+
479
+ = PGroongaのスコアリング\nTF-IDF
480
+
481
+ # coderay sql
482
+
483
+ CREATE TABLE memos (
484
+ title text,
485
+ content text
486
+ );
487
+
488
+ CREATE INDEX pgroonga_memos_index
489
+ ON memos
490
+ USING pgroonga (content);
491
+ INSERT INTO memos VALUES ('PostgreSQL', 'PostgreSQLはリレーショナル・データベース管理システムです。');
492
+ INSERT INTO memos VALUES ('Groonga', 'Groongaは日本語対応の高速な全文検索エンジンです。');
493
+ INSERT INTO memos VALUES ('PGroonga', 'PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。');
494
+ INSERT INTO memos VALUES ('コマンドライン', 'groongaコマンドがあります。');
495
+
496
+ SELECT *, pgroonga_score(tableoid, ctid) AS score
497
+ FROM memos
498
+ WHERE content &@~
499
+ ('PostgreSQL OR 検索',
500
+ ARRAY[1],
501
+ ARRAY['scorer_tf_idf($index)'],
502
+ 'pgroonga_memos_index')::pgroonga_full_text_search_condition_with_scorers
503
+ ORDER BY score DESC;
504
+
505
+ = PGroongaのスコアリング\nTF-IDF
506
+
507
+ # RT
508
+ delimiter = [|]
509
+
510
+ title | score
511
+
512
+ Groonga | 1.3862943649291992
513
+ PostgreSQL | 1
514
+ PGroonga | 1
515
+
516
+ = 参考資料
517
+
518
+ * PGroonga自体の解説
519
+
520
+ * ((<URL:https://www.slideshare.net/kou/postgresql-conference-japan-2017>))