rabbit-slide-kou-mysql-and-postgresql-and-japanese-full-text-search-3 2016.9.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3bc6d689060f78211a40d95c1205655a49bb908e
4
+ data.tar.gz: 6538eff06dc04f6ddb770b6d62dcf49e2886755a
5
+ SHA512:
6
+ metadata.gz: 8f940a73aa12fb0f0690bb01c9d87d2f5f2d7dce5f06d6d303083c231c4b6fd80452e56a3b5e750cf3f708f7b1255502d8ac5fde70c2df0b9b315dcd7cbd7049
7
+ data.tar.gz: 54ce10dcd062a0f535375f7ba9a00c3b67b92e81b7a8adb25d8d9d5a8a37fd04eed3aaccb379a5c5e1b1789efa6414fd8d85071f28e48c36f3a51de0b911063f
data/.rabbit ADDED
@@ -0,0 +1 @@
1
+ mroonga-and-pgroonga.rab
data/README.rd ADDED
@@ -0,0 +1,46 @@
1
+ = Mroonga・PGroonga利用方法
2
+
3
+ Mroonga・PGroongaをさわり始めた人向けにMroonga・PGroongaを利用する方法を具体的な事例を使いながら紹介します。
4
+
5
+ == ライセンス
6
+
7
+ === スライド
8
+
9
+ CC BY-SA 4.0
10
+
11
+ 原著作者名は以下の通りです。
12
+
13
+ * 須藤功平(またはKouhei Sutou)
14
+
15
+ === 画像
16
+
17
+ ==== Groonga・Mroonga・PGroongaのロゴ
18
+
19
+ CC BY 3.0
20
+
21
+ 原著作者名は以下の通りです。
22
+
23
+ * Groongaプロジェクト
24
+ * Mroongaプロジェクト
25
+ * PGroongaプロジェクト
26
+
27
+ == 作者向け
28
+
29
+ === 表示
30
+
31
+ rake
32
+
33
+ === 公開
34
+
35
+ rake publish
36
+
37
+ == 閲覧者向け
38
+
39
+ === インストール
40
+
41
+ gem install rabbit-slide-kou-mysql-and-postgresql-and-japanese-full-text-search-3
42
+
43
+ === 表示
44
+
45
+ rabbit rabbit-slide-kou-mysql-and-postgresql-and-japanese-full-text-search-3.gem
46
+
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("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,27 @@
1
+ ---
2
+ id: mysql-and-postgresql-and-japanese-full-text-search-3
3
+ base_name: mroonga-and-pgroonga
4
+ tags:
5
+ - rabbit
6
+ - mroonga
7
+ - mysql
8
+ - pgroonga
9
+ - postgresql
10
+ - full-text-search
11
+ presentation_date: 2016-09-29
12
+ version: 2016.9.29.0
13
+ licenses:
14
+ - CC BY 3.0
15
+ - CC BY-SA 4.0
16
+ slideshare_id: mysql-and-postgresql-and-japanese-full-text-search-3
17
+ speaker_deck_id:
18
+ ustream_id:
19
+ vimeo_id:
20
+ youtube_id:
21
+ author:
22
+ markup_language: :rd
23
+ name: 須藤功平
24
+ email: kou@clear-code.com
25
+ rubygems_user: kou
26
+ slideshare_user: kou
27
+ speaker_deck_user:
Binary file
@@ -0,0 +1,652 @@
1
+ = Mroonga\n(('note:と'))\nPGroonga
2
+
3
+ : subtitle
4
+ 導入方法例
5
+ : author
6
+ 須藤功平
7
+ : institution
8
+ クリアコード
9
+ : content-source
10
+ MySQLとPostgreSQLと日本語全文検索
11
+ : date
12
+ 2016-09-29
13
+ : allotted-time
14
+ 20m
15
+ : theme
16
+ groonga
17
+
18
+ = Mroonga・PGroonga
19
+
20
+ * Mroonga(むるんが)
21
+ * (('wait'))MySQLに\n
22
+ 高速日本語全文検索機能を追加する\n
23
+ プロダクト
24
+ * PGroonga(ぴーじーるんが)
25
+ * (('wait'))PostgreSQLに\n
26
+ 高速日本語全文検索機能を追加する\n
27
+ プロダクト
28
+
29
+ = 高速?
30
+
31
+ # image
32
+ # src = http://slide.rabbit-shocker.org/authors/kou/mysql-and-postgresql-and-japanese-full-text-search/mroonga-and-pgroonga.pdf
33
+ # page = 6
34
+ # relative_height = 80
35
+
36
+ (('tag:center'))
37
+ (('note:詳細は第1回の資料を参照'))\n
38
+ (('note:http://slide.rabbit-shocker.org/authors/kou/mysql-and-postgresql-and-japanese-full-text-search/'))
39
+
40
+ = 導入方法例
41
+
42
+ 既存システムへの導入方法を紹介
43
+
44
+ * Redmine
45
+ * チケット管理システム
46
+ * Ruby on Redmineを使用
47
+ * Zulip
48
+ * チャットツール
49
+ * Djangoを使用
50
+
51
+ = Redmine
52
+
53
+ # image
54
+ # src = images/redmine-full-text-search-form.png
55
+ # relative_width = 100
56
+
57
+ = 全文検索プラグイン
58
+
59
+ GitHub: (('tag:x-small:okkez/redmine_full_text_search'))
60
+
61
+ * MySQL・PostgreSQL両方対応
62
+ * MySQLのときはMroongaを利用
63
+ * PostgreSQLのときはPGroongaを利用
64
+
65
+ = 速さ
66
+
67
+ (('tag:center'))
68
+ MySQL + Mroongaのケース
69
+
70
+ # RT
71
+ delimiter = [|]
72
+
73
+ プラグイン | チケット数 | 時間
74
+
75
+ なし | 約3000件 | 467ms
76
+ あり | 約3000件 | 93ms
77
+ あり | 約200万件 | 380ms
78
+
79
+ == スライドプロパティ
80
+
81
+ : groonga-product
82
+
83
+ mroonga
84
+
85
+ = 速さ:コメント
86
+
87
+ # image
88
+ # src = images/redmine-full-text-search-plugin-report.png
89
+ # relative_height = 85
90
+
91
+ (('note:https://twitter.com/akahane92/status/733832496945594368'))
92
+
93
+ == スライドプロパティ
94
+
95
+ : groonga-product
96
+
97
+ mroonga
98
+
99
+ = 使いどころ
100
+
101
+ * Mroonga
102
+ * (('wait'))速さが欲しい
103
+ * (('wait'))トランザクションはいらない
104
+ * PGroonga
105
+ * (('wait'))機能が欲しい
106
+ * (('wait'))トランザクションも欲しい
107
+
108
+ = Redmine
109
+
110
+ * トランザクション必須
111
+ * Mroongaを使うときは一工夫必要
112
+ * PGroongaはそのままで大丈夫
113
+
114
+ = Redmine+Mroonga:方針
115
+
116
+ * (('wait'))チケットテーブルは変えない
117
+ * (('wait'))全文検索用テーブルを別途作成
118
+ * (('wait'))全文検索用テーブルから\n
119
+ チケットテーブルを参照
120
+
121
+ == スライドプロパティ
122
+
123
+ : groonga-product
124
+
125
+ mroonga
126
+
127
+ = マイグレーション
128
+
129
+ # coderay ruby
130
+
131
+ def up
132
+ create_table(:fts_issues, # 全文検索用テーブル作成
133
+ id: false, # idは有効・無効どっちでも可
134
+ options: "ENGINE=Mroonga") do |t|
135
+ t.belongs_to :issue, index: true, null: false
136
+ t.string :subject, default: "", null: false
137
+ t.text :description, limit: 65535, null: false
138
+ end
139
+ execute("INSERT INTO " + # データをコピー
140
+ "fts_issues(issue_id, subject, description) " +
141
+ "SELECT id, subject, description FROM issues;")
142
+ add_index(:fts_issues, [:subject, :description],
143
+ type: "fulltext") # 静的インデックス構築(速い)
144
+ end
145
+
146
+ == スライドプロパティ
147
+
148
+ : groonga-product
149
+
150
+ mroonga
151
+
152
+ = モデル
153
+
154
+ # coderay ruby
155
+
156
+ class FtsIssue < ActiveRecord::Base
157
+ # 実際はissue_idカラムは主キーではない。
158
+ # 主キーなしのテーブルなので
159
+ # Active Recordをごまかしているだけ。
160
+ self.primary_key = :issue_id
161
+ belongs_to :issue
162
+ end
163
+
164
+ == スライドプロパティ
165
+
166
+ : groonga-product
167
+
168
+ mroonga
169
+
170
+ = 保存
171
+
172
+ # coderay ruby
173
+
174
+ class Issue
175
+ # この後にロールバックされることがあるのでカンペキではない
176
+ # 再度同じチケットを更新するかデータを入れ直せば直る
177
+ after_safe do |record|
178
+ fts_record =
179
+ FtsIssue.find_or_initialize_by(issue_id: record.id)
180
+ fts_record.subject = record.subject
181
+ fts_record.description = record.description
182
+ fts_record.save!
183
+ end
184
+ end
185
+
186
+ == スライドプロパティ
187
+
188
+ : groonga-product
189
+
190
+ mroonga
191
+
192
+ = 全文検索
193
+
194
+ # coderay ruby
195
+
196
+ issue.
197
+ joins(:fts_issue).
198
+ where(["MATCH(fts_issues.subject, " +
199
+ "fts_issues.description) " +
200
+ "AGAINST (? IN BOOLEAN MODE)",
201
+ # ↓デフォルトANDで全文検索
202
+ "*D+ #{keywords.join(', ')}"])
203
+
204
+ == スライドプロパティ
205
+
206
+ : groonga-product
207
+
208
+ mroonga
209
+
210
+ = Redmine+Mroonga:まとめ
211
+
212
+ * (('wait'))トランザクション必須
213
+ * 元テーブルを置き換えない
214
+ * 全文検索用テーブルを作成
215
+ * (('wait'))データ
216
+ * アプリが複数テーブルに保存
217
+ * (('wait'))全文検索
218
+ * ((*JOIN*))して((*MATCH AGAINST*))
219
+
220
+ == スライドプロパティ
221
+
222
+ : groonga-product
223
+
224
+ mroonga
225
+
226
+ = Redmine+PGroonga:方針
227
+
228
+ * (('wait'))全文検索用インデックス作成
229
+ * (('wait'))インデックスに主キーを含める
230
+ * 検索スコアーを取得するため
231
+
232
+ == スライドプロパティ
233
+
234
+ : groonga-product
235
+
236
+ pgroonga
237
+
238
+ = マイグレーション
239
+
240
+ # coderay ruby
241
+
242
+ def up
243
+ enable_extension("pgroonga")
244
+ add_index(:issues,
245
+ [:id, :subject, :description],
246
+ using: "pgroonga")
247
+ end
248
+
249
+ == スライドプロパティ
250
+
251
+ : groonga-product
252
+
253
+ pgroonga
254
+
255
+ = モデル
256
+
257
+ 追加・変更なし
258
+
259
+ == スライドプロパティ
260
+
261
+ : groonga-product
262
+
263
+ pgroonga
264
+
265
+ = 保存
266
+
267
+ 追加・変更なし
268
+
269
+ == スライドプロパティ
270
+
271
+ : groonga-product
272
+
273
+ pgroonga
274
+
275
+ = 全文検索
276
+
277
+ # coderay ruby
278
+
279
+ issue.
280
+ # 検索対象のカラムごとに
281
+ # クエリーを指定
282
+ where(["subject @@ ? OR " +
283
+ "description @@ ?",
284
+ keywords.join(", "),
285
+ keywords.join(", ")])
286
+
287
+ == スライドプロパティ
288
+
289
+ : groonga-product
290
+
291
+ pgroonga
292
+
293
+ = Redmine+PGroonga:まとめ
294
+
295
+ * (('wait'))インデックス追加のみでOK
296
+ * トランザクション対応
297
+ * データ保存も変更なし
298
+ * (('wait'))全文検索
299
+
300
+ # coderay sql
301
+ カラム1 @@ 'クエリー' OR
302
+ カラム2 @@ 'クエリー' OR ...
303
+
304
+ == スライドプロパティ
305
+
306
+ : groonga-product
307
+
308
+ pgroonga
309
+
310
+ = Redmine:まとめ
311
+
312
+ * (('wait'))速い!
313
+ * (('wait'))Mroonga
314
+ * 全文検索用テーブルで実現
315
+ * (('wait'))PGroonga
316
+ * 全文検索用インデックスで実現
317
+
318
+ = Zulip
319
+
320
+ # image
321
+ # src = images/zulip-full-text-search-form.png
322
+ # relative_height = 95
323
+
324
+ = Zulipの全文検索機能
325
+
326
+ * (('wait'))現在:textsearch
327
+ * PostgreSQL標準機能
328
+ * 英語のみ対応
329
+ * (('wait'))NEW!:PGroonga
330
+ * オプション(=PGroongaに切替可)
331
+ * 全言語対応(日本語を含む)
332
+
333
+ == スライドプロパティ
334
+
335
+ : groonga-product
336
+
337
+ pgroonga
338
+
339
+ = Zulip+PGroonga:方針
340
+
341
+ * 書き込み速度を落とさない
342
+ * チャットは書き込みが遅いと微妙
343
+ * インデックスは裏で更新\n
344
+ (('note:PGroongaならリアルタイム更新でも大丈夫かも'))
345
+
346
+ (('note:詳細:https://github.com/zulip/zulip/pull/700/files'))
347
+
348
+ == スライドプロパティ
349
+
350
+ : groonga-product
351
+
352
+ pgroonga
353
+
354
+ = マイグレーション
355
+
356
+ # coderay python
357
+
358
+ migrations.RunSQL("""
359
+ ALTER ROLE zulip SET search_path
360
+ TO zulip,public,pgroonga,pg_catalog;
361
+ ALTER TABLE zerver_message
362
+ ADD COLUMN search_pgroonga text;
363
+ UPDATE zerver_message SET search_pgroonga =
364
+ subject || ' ' || rendered_content;
365
+ CREATE INDEX pgrn_index ON zerver_message
366
+ USING pgroonga(search_pgroonga);
367
+ """, "...")
368
+
369
+ == スライドプロパティ
370
+
371
+ : groonga-product
372
+
373
+ pgroonga
374
+
375
+ = 遅延インデックス更新
376
+
377
+ * メッセージ追加・更新時にログ
378
+ * 別プロセスでログを監視
379
+
380
+ == スライドプロパティ
381
+
382
+ : groonga-product
383
+
384
+ pgroonga
385
+
386
+ = 追加・更新時にログ
387
+
388
+ # coderay sql
389
+
390
+ CREATE FUNCTION append_to_fts_update_log()
391
+ RETURNS trigger
392
+ LANGUAGE plpgsql AS $$
393
+ BEGIN
394
+ INSERT INTO fts_update_log (message_id)
395
+ VALUES (NEW.id);
396
+ RETURN NEW;
397
+ END
398
+ $$;
399
+ CREATE TRIGGER update_fts_index_async
400
+ BEFORE INSERT OR UPDATE OF
401
+ subject, rendered_content ON zerver_message
402
+ FOR EACH ROW
403
+ EXECUTE PROCEDURE append_to_fts_update_log();
404
+
405
+ == スライドプロパティ
406
+
407
+ : groonga-product
408
+
409
+ pgroonga
410
+
411
+ = 別プロセスに通知
412
+
413
+ # coderay sql
414
+
415
+ CREATE FUNCTION do_notify_fts_update_log()
416
+ RETURNS trigger
417
+ LANGUAGE plpgsql AS $$
418
+ BEGIN
419
+ NOTIFY fts_update_log;
420
+ RETURN NEW;
421
+ END
422
+ $$;
423
+ CREATE TRIGGER fts_update_log_notify
424
+ AFTER INSERT ON fts_update_log
425
+ FOR EACH STATEMENT
426
+ EXECUTE PROCEDURE do_notify_fts_update_log();
427
+
428
+ == スライドプロパティ
429
+
430
+ : groonga-product
431
+
432
+ pgroonga
433
+
434
+ = インデックス更新プロセス
435
+
436
+ # coderay python
437
+
438
+ import psycopg2
439
+ conn = psycopg2.connect("user=zulip")
440
+ cursor = conn.cursor
441
+ cursor.execute("LISTEN fts_update_log;")
442
+ while True:
443
+ if select.select([conn], [], [], 30) != ([], [], []):
444
+ conn.poll()
445
+ while conn.notifies:
446
+ conn.notifies.pop()
447
+ update_fts_columns(cursor)
448
+
449
+ == スライドプロパティ
450
+
451
+ : groonga-product
452
+
453
+ pgroonga
454
+
455
+ = インデックス更新
456
+
457
+ # coderay python
458
+
459
+ def update_fts_columns(cursor):
460
+ cursor.execute("SELECT id, message_id "
461
+ "FROM fts_update_log;")
462
+ ids = []
463
+ for (id, message_id) in cursor.fetchall():
464
+ cursor.execute("UPDATE zerver_message SET "
465
+ "search_pgroonga = "
466
+ "subject || ' ' || rendered_content "
467
+ "WHERE id = %s", (message_id,))
468
+ ids.append(id)
469
+ cursor.execute("DELETE FROM fts_update_log "
470
+ "WHERE id = ANY(%s)", (ids,))
471
+
472
+ == スライドプロパティ
473
+
474
+ : groonga-product
475
+
476
+ pgroonga
477
+
478
+ = 全文検索
479
+
480
+ # coderay python
481
+
482
+ from sqlalchemy.sql import column
483
+ def _by_search_pgroonga(self, query, operand):
484
+ # WHERE search_pgroonga @@ 'クエリー'
485
+ target = column("search_pgroonga")
486
+ condition = target.op("@@")(operand)
487
+ return query.where(condition)
488
+
489
+ == スライドプロパティ
490
+
491
+ : groonga-product
492
+
493
+ pgroonga
494
+
495
+ = ハイライト
496
+
497
+ # image
498
+ # src = images/zulip-highlight.png
499
+ # relative_height = 95
500
+
501
+ == スライドプロパティ
502
+
503
+ : groonga-product
504
+
505
+ pgroonga
506
+
507
+ = ハイライト:SQL
508
+
509
+ # coderay sql
510
+
511
+ SELECT
512
+ pgroonga.match_positions_byte(
513
+ rendered_content,
514
+ pgroonga.query_extract_keywords('クエリー'))
515
+ AS content_matches,
516
+ pgroonga.match_positions_byte(
517
+ subject,
518
+ pgroonga.query_extract_keywords('クエリー'))
519
+ AS subject_matches
520
+
521
+ == スライドプロパティ
522
+
523
+ : groonga-product
524
+
525
+ pgroonga
526
+
527
+ = ハイライト:SQLAlchemy
528
+
529
+ # coderay python
530
+
531
+ from sqlalchemy import func
532
+ def _by_search_pgroonga(self, query, operand):
533
+ match_positions_byte = func.pgroonga.match_positions_byte
534
+ query_extract_keywords = func.pgroonga.query_extract_keywords
535
+ keywords = query_extract_keywords(operand)
536
+ query = query.column(
537
+ match_positions_byte(column("rendered_content"),
538
+ keywords).label("content_matches"))
539
+ query = query.column(
540
+ match_positions_byte(column("subject"),
541
+ keywords).label("subject_matches"))
542
+ # ...
543
+
544
+ == スライドプロパティ
545
+
546
+ : groonga-product
547
+
548
+ pgroonga
549
+
550
+ = ハイライト:Python
551
+
552
+ # coderay python
553
+
554
+ def highlight_string_bytes_offsets(text, locs):
555
+ # type: (AnyStr, Iterable[Tuple[int, int]]) -> text_type
556
+ string = text.encode('utf-8')
557
+ highlight_start = b'<span class="highlight">'
558
+ highlight_stop = b'</span>'
559
+ pos = 0
560
+ result = b''
561
+ for loc in locs:
562
+ (offset, length) = loc
563
+ result += string[pos:offset]
564
+ result += highlight_start
565
+ result += string[offset:offset + length]
566
+ result += highlight_stop
567
+ pos = offset + length
568
+ result += string[pos:]
569
+ return result.decode('utf-8')
570
+
571
+ == スライドプロパティ
572
+
573
+ : groonga-product
574
+
575
+ pgroonga
576
+
577
+ = ハイライト:補足
578
+
579
+ * 通常はハイライト関数で十分
580
+ * (({pgroonga.highlight_html}))
581
+ * ただし(({ts_headline}))では不十分
582
+ * HTML出力に使えない
583
+
584
+ == スライドプロパティ
585
+
586
+ : groonga-product
587
+
588
+ pgroonga
589
+
590
+ = ハイライト:ts_headline
591
+
592
+ # coderay sql
593
+
594
+ SELECT
595
+ ts_headline('english',
596
+ 'PostgreSQL <is> great!',
597
+ to_tsquery('PostgreSQL'),
598
+ 'HighlightAll=TRUE');
599
+ -- ts_headline
600
+ -- -------------------------------
601
+ -- <b>PostgreSQL</b> <is> great!
602
+ -- (1 row) 不正なHTML↑
603
+
604
+ == スライドプロパティ
605
+
606
+ : groonga-product
607
+
608
+ pgroonga
609
+
610
+ = ハイライト:pgroonga.highlight_html
611
+
612
+ # coderay sql
613
+
614
+ SELECT
615
+ pgroonga.highlight_html(
616
+ 'PostgreSQL <is> great!',
617
+ pgroonga.query_extract_keywords('PostgreSQL'));
618
+ -- highlight_html
619
+ -- ----------------------------------------
620
+ -- <span class="keyword">PostgreSQL</span>
621
+ -- &lt;is&gt; great!
622
+ -- ↑ ↑HTMLエスケープされている
623
+
624
+ == スライドプロパティ
625
+
626
+ : groonga-product
627
+
628
+ pgroonga
629
+
630
+ = Zulip:まとめ
631
+
632
+ * (('wait'))全言語対応全文検索
633
+ * textsearch(1言語のみ)→\n
634
+ PGroonga(全言語)
635
+ * (('wait'))書き込み性能は維持
636
+ * 遅延インデックス更新
637
+
638
+ == スライドプロパティ
639
+
640
+ : groonga-product
641
+
642
+ pgroonga
643
+
644
+ = まとめ
645
+
646
+ * (('wait'))Mroonga・PGroongaの\n
647
+ 導入方法を実例ベースで紹介
648
+ * Redmine:チケット管理システム
649
+ * Zulip:チャットツール
650
+ * (('wait'))トランザクション必須の場合
651
+ * Mroonga:別テーブル作成
652
+ * PGroonga:インデックス追加
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbit-slide-kou-mysql-and-postgresql-and-japanese-full-text-search-3
3
+ version: !ruby/object:Gem::Version
4
+ version: 2016.9.29.0
5
+ platform: ruby
6
+ authors:
7
+ - 須藤功平
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rabbit
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.2
27
+ description: Mroonga・PGroongaをさわり始めた人向けにMroonga・PGroongaを利用する方法を具体的な事例を使いながら紹介します。
28
+ email:
29
+ - kou@clear-code.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rabbit"
35
+ - README.rd
36
+ - Rakefile
37
+ - config.yaml
38
+ - images/redmine-full-text-search-form.png
39
+ - images/redmine-full-text-search-plugin-report.png
40
+ - images/zulip-full-text-search-form.png
41
+ - images/zulip-highlight.png
42
+ - mroonga-and-pgroonga.rab
43
+ - pdf/mysql-and-postgresql-and-japanese-full-text-search-3-mroonga-and-pgroonga.pdf
44
+ homepage: http://slide.rabbit-shocker.org/authors/kou/mysql-and-postgresql-and-japanese-full-text-search-3/
45
+ licenses:
46
+ - CC BY 3.0
47
+ - CC BY-SA 4.0
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.5.1
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Mroonga・PGroonga利用方法
69
+ test_files: []