PHP で PostgreSQL と PGroonga を使って高速日本語全文検索! 須藤功平 クリアコード 第 115 回 PHP 東京 PHP で PostgreSQL と PGroonga を使って高速日本語全文検索! Powered by Rabbit 2.

Similar documents
よく活用された Redmine 情報の宝庫問題解決の経緯 Wiki に整理したノウハウ

メール全文検索アプリケーション Sylph-Searcher のご紹介 SRA OSS, Inc. 日本支社技術部チーフエンジニア Sylpheed 開発者 山本博之 Copyright 2007 SRA OSS, Inc. Japan All right

Apache Arrow 須藤功平株式会社クリアコード RubyData Tokyo Meetup Apache Arrow Powered by Rabbit 2.2.2

10th Developer Camp - B5

Si 知識情報処理

◎phpapi.indd

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

IronPython による柔軟なゲーム開発 筑波大学 AmusementCreators

全文検索 Google Bing が提供している機能

内容 Visual Studio サーバーエクスプローラで学ぶ SQL とデータベース操作... 1 サーバーエクスプローラ... 4 データ接続... 4 データベース操作のサブメニューコンテキスト... 5 データベースのプロパティ... 6 SQL Server... 6 Microsoft

ウェブサービスとは WWWを介してデータの取得 解析などをサー バ側で行うサービス 人が直接使うことは意図されていない プログラム等を使って大量に処理できる(単純) 作業を意図している SOAP, REST

intra-mart Accel Platform — IM-共通マスタ スマートフォン拡張プログラミングガイド   初版  

JavaScript の使い方

勉強会の流れ Google API の概要 デモ curl で実際に体験 Copyright 2010 SRA OSS, Inc. Japan All rights reserved. 2

XAMPP で CMS のお手軽 テスト環境を手に入れよう 2011/5/21 上村崇 1

PowerPoint プレゼンテーション

intra-mart Accel Platform — IM-BloomMaker プログラミングガイド   初版  

PowerPoint プレゼンテーション

PostgreSQL 9.4 評価検証報告 SRA OSS, Inc. 日本支社高塚遙 :55 ~ 16:30 PostgreSQL 9.4 最新情報セミナー Copyright 2014 SRA OSS, Inc. Japan All rights reserved. 1

ソフトウェアエンジニアリング - 機能 #54

Exam : 1z0-882 日本語 (JPN) Title : Oracle Certified Professional, MySQL 5.6 Developer Vendor : Oracle Version : DEMO 1 / 4 Get Latest & Valid 1z0-882-JP

PowerPoint Presentation

Microsoft PowerPoint - download.ppt

Jupyter Notebook を活用したプログラムライブラリ構築の検討 吹谷芳博 1, 藤澤正樹 1 ( 1 あすか製薬株式会社 ) Examination of the program library construction using Jupyter Notebook ASKA Pharm

JavaScript 演習 2 1

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

データベースアクセス

スライド 1

昨年度までの研究紹介 および 研究計画

Sylpheed とは オープンソースのメールソフト ライセンスは GPL+LGPL 高速 軽量 高機能 高い操作性 高い信頼性 導入が容易 マルチプラットフォーム Windows, Linux, etc. 多言語対応 ( 約 30 ヶ国語 )

PostgreSQL カンファレンス 2013 証券取引バックオフィスにおける Oracle から PostgreSQL への マイグレーション SBI ジャパンネクスト証券株式会社 イアン バーウィック

テンプレートエンジンの必要性 昔 (2000 年ごろ?) の典型的な PHP のコード : <?php // 処理?> <html> <body> <?php print("hello World!");?> </body> </html> 以下のような問題で衝突していた 1 一旦プログラムコードを

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版   None

nlp1-12.key

InstallShield FAQ < 独自の InstallShield 前提条件を作成する > 注 ) このドキュメントは InstallShield 2014 Premier Edition を基に作成しています InstallShield 2014 以外のバージョンでは設定名などが異なる場合

ii II Web Web HTML CSS PHP MySQL Web Web CSS JavaScript Web SQL Web

ご利用のコンピュータを設定する方法 このラボの作業を行うには 事前設定された dcloud ラボを使用するか 自身のコンピュータをセットアップします 詳細については イベントの事前準備 [ 英語 ] とラボの設定 [ 英語 ] の両方のモジュールを参照してください Python を使用した Spar

Microsoft Word - CBESNet-It連携ガイドver8.1.doc

,, create table drop table alter table

モバイルアプリを Azure で作る - データを扱う Azure Storage を利 してデータを保存する 本稿では PHP と Windows Azure を使って 画像などのファイルを扱うアプリケーションを開発する方法を説明します Windows Azure Platform では データの

Sinatra と MongoDB 今回は Sinatra で MongoDB の操作を体験してみます 進捗に合わせて ドライバから Ruby で使える便利な ORM の紹介をします

PowerPoint Presentation

Brekeke PBX - Version 2.1 ARSプラグイン開発ガイド

MVC4 Mobile Classic

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

Postgres Plus Advanced Server 9.3パーティションテーブルの特徴と性能検証レポート

プログラミング入門1

1

グーグル検索マクロの使い方

Web WIX WIX WIX Web Web Web WIX WIX WIX Web 3. Web Index 3. 1 Web Index (WIX), Web. Web, WIX, Web ( WIX ), URL WIX 1 entry wid eid keyword targe

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版  

Taro-QGIS 3.2

FS_handbook.indd

タグ付きPDFとは何か?

高速 軽量メールクライアント Sylpheed の応用ソリューション 高速全文検索機能 (Sylph-searcher) メールライブラリ (LibSylph) OpenSource Conference 2009 Tokyo/Spring SRA OSS, Inc. 日本支社山本博之 Copyri

Consuming a simple Web Service

Transcription:

PHP で PostgreSQL と PGroonga を使って高速日本語全文検索! 須藤功平 クリアコード 第 115 回 PHP 勉強会 @ 東京 2017-06-28

PostgreSQL と全文検索 LIKE: 組込機能 textsearch: 組込機能 pg_trgm: 標準添付 アーカイブには含まれている別途インストールすれば使える

LIKE 少ないデータ 十分実用的 400 文字 20 万件くらいなら1 秒とか 少なくないデータ 性能問題アリ

textsearch インデックスを作るので速い 言語毎にモジュールが必要 英語やフランス語などは組込 日本語は別途必要 日本語用モジュール 公式にはメンテナンスされていない fork して動くようにしている人はいる

pg_trgm インデックスを作るので速い 注 : ヒット件数が増えると遅い注 : テキスト量が多いと遅い注 :1,2 文字の検索は遅い ( 米 日本 ) 日本語を使うにはひと工夫必要 C.UTF-8を使うソースを変更してビルド

プラグイン pg_bigm pg_trgm の日本語対応強化版 PGroonga 本気の全文検索エンジンを利用速いし日本語もバッチリ!

ベンチマーク :pg_bigm Elapsed time (sec) (Lower is better) 3 2.5 2 1.5 1 0.5 pg_bigm Data: Japanese Wikipedia (Many records and large documents) N records: About 0.9millions Average text size: 6.7KiB Slow Slow 0 311 14706 20389 N hits

Elapsed time (sec) (Lower is better) ベンチマーク :PGroonga 3 2.5 2 1.5 1 0.5 PGroonga Data: Japanese Wikipedia (Many records and large documents) N records: About 0.9millions Average text size: 6.7KiB Fast Fast 0 311 14706 20389 N hits pg_bigm

よし! PostgreSQL と PGroonga を使って 高速日本語全文検索サービスを PHP で作ろう!

PHP document search

機能 検索キーワードハイライトキーワード周辺テキスト表示オートコンプリート ローマ字対応 (seiki 正規表現 )

作り方 : ツール フレームワーク Laravel RDBMS PostgreSQL 高速日本語全文検索機能 PGroonga

作り方 : インストール Laravel 省略 PostgreSQL パッケージで PGroonga パッケージで https://pgroonga.github.io/ja/install/

初期化 :Laravel % laravel new php-document-search % cd php-document-search % editor.env

初期化 : データベース % sudo -u postgres -H \ createdb php_document_search

初期化 :PGroonga -- を実行する必要がある CREATE EXTENSION pgroonga;

初期化 :PGroonga マイグレーションファイル作成 % php artisan \ make:migration enable_pgroonga

マイグレーション public function up() { DB::statement("CREATE EXTENSION pgroonga;"); } public function down() { DB::statement("DROP EXTENSION pgroonga;"); }

モデル作成 ドキュメントはモデル 名前 :Entry 1 ページ 1 インスタンス

モデル作成 % php artisan \ make:model \ --migration \ --controller \ --resource \ Entry

マイグレーション public function up() { Schema::create('entries', function ($table) { $table->increments('id'); table->text('url'); $table->text('title'); $table->text('content'); // PGroonga 用インデックス デフォルトで全文検索用 // 主キー (id) も入れるのが大事! スコアー取得に必要 $table->index( ['id', 'title', 'content'], null, 'pgroonga'); }); }

データ登録 1. PHP のドキュメントをローカルで生成 PHP のドキュメントの作り方 http://doc.php.net/tutorial/ フィードバックチャンスがいろいろあったよ!( 後述 ) 2. ページ毎に PostgreSQL に挿入

コマンド作成 % php artisan \ make:command \ --command=doc:register \ RegisterDocuments

登録コマンド実装 ( 一部 ) public function handle() { foreach (glob("public/doc/*.html") as $html_path) { $document = new \DOMDocument(); @$document->loadhtmlfile($html_path); $xpath = new \DOMXPath($document); $entry = new Entry(); $entry->url = "/doc/". basename($html_path); // XPath でテキスト抽出 $this->extract_title($entry, $xpath); $this->extract_content($entry, $xpath); $entry->save(); } }

登録 % php artisan doc:register

検索用コントローラー public function index(request $request) { $query = $request['query']; $entries = Entry::query() // はモデルに作る ( 後述 ) ->fulltextsearch($query) ->limit(10) ->get(); return view('entry.search.index', [ 'entries' => $entries, 'query' => $query, ]); }

検索対象モデル public function scopefulltextsearch($query, $search_query) { if ($search_query) { return...; // クエリーがあったら検索 } else { return...; // なかったら適当に返す ( 省略 ) } }

検索対象モデル : 検索 return $query ->select('id', 'url') // 適合度をスコアーとして返す ->selectraw('pgroonga.score(entries) AS score') // キーワードハイライト ->highlighthtml('title', $search_query) // キーワード周辺のテキスト ( キーワードハイライト付き ) ->snippethtml('content', $search_query) // タイトルと本文を全文検索 ( 後で補足 ) ->whereraw('title @@? OR content @@?', [$search_query, $search_query]) // それっぽい文書の順に返す ->orderby('score', 'DESC');

キーワードハイライト public function scopehighlighthtml($query, $column, $search_query) { return $query // PGroonga 提供ハイライト関数 ->selectraw("pgroonga.highlight_html($column, ". // PGroonga 提供クエリーからキーワードを抽出する関数 "pgroonga.query_extract_keywords(?)) ". "AS highlighted_$column", [$search_query]); }

検索結果 <div class="entries"> @foreach ($entries as $entry) <a href="{{ $entry->url }}"> <h4> {{-- マークアップ済み! --}} {!! $entry->highlighted_title!!} <span class="score">{{ $entry->score }}</span> </h4> {{-- 周辺テキストは text[]( 後で補足 ) --}} @foreach ($entry->content_snippets as $snippet) <pre class="snippet">{!! $snippet!!}</pre> @endforeach </a> @endforeach </div>

検索対象モデル : 配列 public function getcontentsnippetsattribute($value) { // PostgreSQL は配列をサポートしているが PDO は未サポート // '["...","..."]' という文字列になるのでそれを配列に変換 return array_map( function ($e) { // " が \" になっているので戻す return preg_replace('/\\\\(.)/', '$1', $e); }, explode('","', substr($value, 2, -2))); }

高速日本語全文検索!

オートコンプリート 必要なもの 候補用テーブル候補のヨミガナ ( カタカナ ) PGroonga!!!

モデル作成 % php artisan \ make:model \ --migration \ --controller \ --resource \ Term

マイグレーション : カラム public function up() { Schema::create('terms', function ($table) { $table->increments('id'); $table->text('term'); $table->text('label'); $table->text('reading'); // 本当は配列にしたい $table->timestamps(); // インデックス定義 ( 後述 ) }); }

マイグレーションインデックス $table->index([ // 候補に対する前方一致検索用 DB::raw('term pgroonga.text_term_search_ops_v2'), // ヨミガナに対する前方一致 RK 検索用 DB::raw('reading pgroonga.text_term_search_ops_v2'), ], null, 'pgroonga'); // 候補に対する全文検索用 ( 中間一致用 ) $table->index([db::raw('term')], null, 'pgroonga');

前方一致 RK 検索 日本語特化の前方一致検索 ローマ字 ひらがな カタカナでカタカナを前方一致検索できる gy ギュウニュウ ぎ ギュウニュウ ギ ギュウニュウ

候補モデル : 検索 public function scopecomplete($query, $search_query) { return $query ->select("label") ->highlighthtml('label', $search_query) ->whereraw("term &^ :query OR ". // 前方一致検索 "reading &^~ :query OR ". // 前方一致 RK 検索 "term @@ :query", // 全文検索 ["query" => $search_query]) ->orderby("label") ->limit(10); }

コントローラー public function index(request $request) { $query = $request["query"]; // モデルに実装した検索処理を呼び出し $terms = Term::query()->complete($query); $data = []; foreach ($terms->get() as $term) { $data[] = [ "value" => $term->label, "label" => $term->highlighted_label, ]; } // JSON で候補を返す return response()->json($data); }

UI $('#query').autocomplete({ source: function(request, response) { $.ajax({ url: "/terms/", // コントローラー呼び出し datatype: "json", data: {query: this.term}, success: response }); } }).autocomplete("instance")._renderitem = function(ul, item) { return $("<li>").attr("data-value", item.value) // 候補には生データを使う.append(item.label) // ハイライトしたデータを表示.appendTo(ul); };

オートコンプリート!

まとめ PGroonga を使えば 高速日本語全文検索サービスを PHP で簡単に作れる! PHP document search のソース https://github.com/kou/php-documentsearch

その他 (1) PHP+MySQL+Mroongaでも簡単! Groongaではじめる全文検索 https://grnbook-ja.tumblr.com/ 著者 : 北市真 PHP+Mroonga 入門の電子書籍今はまだ無料!

その他 (2) だれか PHP document search をメンテナンスしませんか? 普通に便利じゃないかと! 複数バージョン対応とか 複数言語対応とか

その他 (3) PHP の開発に参加しませんか? PDOのPostgreSQL 対応強化とかドキュメントまわりとか やりたいけど自分はムリそう そんなことはないんですよ!

その他 (4) OSS Gate ワークショップ OSS 開発未経験者を経験者にするワークショップ PHP も OSS! 次回は 7 月 29 日 https://oss-gate.doorkeeper.jp/events/ upcoming

その他 (5) PHP カンファレンス 2017 内で OSS Gate ワークショップ開催はどうですか!? PHP 関連の OSS の開発に参加する人が増えるとうれしい? うれしいならコラボできそう