HAYASHI Kentaro
hayas****@clear*****
2012年 11月 29日 (木) 10:47:37 JST
林です。 今日は全文検索エンジンgroongaを囲む夕べ 3の開催日ですね。 http://atnd.org/events/33070 [groongaを囲む夕べ 3に関するお願い] キャンセル待ちの方もおられますので、参加者で都合が悪くなってしまった方は お早めにATNDよりキャンセル手続きをしていただけると助かります。 groonga 2.0.9をリリースしました! groonga2.0.9はgroonga 2.xのメンテナンスリリースです。 http://groonga.org/ja/docs/news.html#release-2-0-9 今回のリリースの主なトピックは 4 つあります。 * snippet_html()関数の実験的なサポート * インデックスにより関連付けられたテーブル間のネストしたインデックス検索のサポート * 指定範囲の検索をサポート * geo_distance()関数で矩形近似により境界をまたぐ二点間の距離計算をサポート それぞれの環境毎のインストール方法はこちらを見てください。 http://groonga.org/ja/docs/install.html ○ snippet_html()関数の実験的なサポート 今回のリリースでは、実験的ではありますが、キーワードとその周辺のテキストを抽出するための snippet_html()関数をサポートしました。 あくまで実験的なので今後予告なく変更する可能性があります。 snippet_html()関数は以下のような構文で使用します。 snippet_html(column名) どんな風に使えるかを具体例で説明します。 以下は説明のためのスキーマ定義とサンプルデータです。 table_create Documents TABLE_NO_KEY column_create Documents content COLUMN_SCALAR Text table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram column_create Terms documents_content_index COLUMN_INDEX|WITH_POSITION Documents content load --table Documents [ ["content"], ["Groonga is a fast and accurate full text search engine based on inverted index."], ["Groonga is also a column-oriented database management system (DBMS)."], ["Mroonga was called groonga storage engine."] ] Documentsテーブルに登録したデータからキーワードgroongaを含むテキストを抽出するには 以下のクエリを実行します。(見た目の都合上クエリを折り返しています) select Documents --output_columns "snippet_html(content)" --command_version 2 --match_columns content --query "groonga" 上記クエリでは検索したいキーワードgroongaを--queryに指定し、 検索対象のカラムには--match_columns contentとしてDocumentテーブルのcontentカラムを指定します。 このとき、クエリにコマンドバージョン(--command_version 2)を指定する必要があります。 これは、--ouput_columnsで関数を呼びだすことができるようになったのは2.0.9からだからです。 結果は以下のようになり、指定したキーワードが<span>タグで囲まれ、キーワード周辺のテキストとして 抽出できていることがわかります。 検索結果のキーワードをハイライト表示したいときに便利な機能です。 [ [0,1353893385.5454,0.000486850738525391], [ [ [3], [["snippet_html","null"]], [["<span class=\"keyword\">Groonga</span> is a fast and accurate full text search engine based on inverted index."]], [["<span class=\"keyword\">Groonga</span> is also a column-oriented database management system (DBMS)."]], [["Mroonga was called <span class=\"keyword\">groonga</span> storage engine."]] ] ] ] snippet_html()関数の詳細については以下のドキュメントを参照してください。 http://groonga.org/ja/docs/reference/functions/snippet_html.html ○ インデックスにより関連付けられたテーブル間のネストしたインデックス検索のサポート 今回のリリースでは複数のテーブルの間でインデックスが張られているなど、 テーブル間の関連が存在する場合にインデックス名をネストして指定することで 複数テーブルからまとめて検索することができるようになりました。 これだけだとわかりにくいので、例を示します。 ブログ記事を格納してるテーブルと記事に対するコメントを格納するテーブルがあるとします。 記事を格納しているテーブルには記事そのもののカラムとコメントテーブルを参照するカラムがあり、 コメントテーブルにはコメントを格納するカラムと、記事テーブルへのインデックスカラムがあるとします。 これまで特定のキーワードをコメントに含む記事を探すには、 コメントテーブルの全文検索と、その全文検索結果から該当記事を検索する必要がありました。 これが、参照先のインデックスカラムを指定することでまとめて検索できるようになりました。 どう使うかのサンプルを以下で示します。 サンプルのスキーマ定義は以下の通りです。 table_create Comments TABLE_HASH_KEY UInt32 column_create Comments content COLUMN_SCALAR ShortText table_create Articles TABLE_NO_KEY column_create Articles content COLUMN_SCALAR Text column_create Articles comment COLUMN_SCALAR Comments table_create Lexicon TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram column_create Lexicon articles_content COLUMN_INDEX|WITH_POSITION Articles content column_create Lexicon comments_content COLUMN_INDEX|WITH_POSITION Comments content column_create Comments article COLUMN_INDEX Articles comment 記事とコメントのサンプルデータは以下のようにして登録します。 load --table Comments [ {"_key": 1, "content": "I'm using groonga too!"}, {"_key": 2, "content": "I'm using groonga and mroonga!"}, {"_key": 3, "content": "I'm using mroonga too!"} ] load --table Articles [ {"content": "Groonga is fast!", "comment": 1}, {"content": "Groonga is useful!"}, {"content": "Mroonga is fast!", "comment": 3} ] コメントテーブルから指定したキーワードを含むレコードを検索し、 そのコメントのレコードを参照しているカラムの記事データを取得するクエリは 以下のように書くことができます。 select Articles --match_columns comment.content --query groonga --output_columns "_id, _score, *" --match_columnsにはArticlesテーブルのcommentカラムとCommentsテーブルのcontentカラムとを ピリオドで連結して指定します。 するとCommentsテーブルのcontentカラムをまずはじめに全文検索し、 該当するレコードを参照しているArticlesのcommentカラムのレコードを取得できる仕組みになっています。 (そのため、上記スキーマ定義でCommentsテーブルにインデックスカラムarticleがない場合、 CommentsテーブルからArticlesテーブルを辿れないので正しい結果が得られません。) [ [0,1353903149.81632,0.000459432601928711], [ [ [1], [["_id","UInt32"],["_score","Int32"],["comment","Comments"],["content","Text"]], [1,1,1,"Groonga is fast!"] ] ] ] 従来から可能であった特定のキーワードを含む記事の全文検索だけでなく、 特定のキーワード(上記の場合はgroonga)を含むコメントを参照している記事を 取得することができるようになりました。 ○ 指定範囲の検索をサポート 今回のリリースでは、範囲を指定した検索を行えるようになりました。 例えば、Time型のカラムで指定した日以前の結果を検索することができるよう になりました。 どう使うかのサンプルを誕生日を例に示します。 サンプルのスキーマ定義は以下の通りです。 table_create Users TABLE_HASH_KEY ShortText column_create Users birthday COLUMN_SCALAR Time table_create Birthdays TABLE_PAT_KEY Time column_create Birthdays users_birthday COLUMN_INDEX Users birthday 以下のように個人の誕生日を登録します。 load --table Users [ {"_key": "Alice", "birthday": "1992-02-09 00:00:00"}, {"_key": "Bob", "birthday": "1988-01-04 00:00:00"}, {"_key": "Carlos", "birthday": "1982-12-29 00:00:00"} ] 誕生日のデータを登録できたので、実際に検索してみます。 ここでは、Bobの誕生日より後の誕生日の人を検索してみます。 誕生日はTime型のカラムに登録してあるので、範囲の指定にはbirthdayに対し てBobの誕生日より後というのを'birthday > "1988-01-04 00:00:00"'として 表現します。 実際の検索結果は以下のようになります。 select Users --filter 'birthday > "1988-01-04 00:00:00"' [ [0,1354069642.52512,0.000299692153930664], [ [ [1], [ ["_id","UInt32"], ["_key","ShortText"], ["birthday","Time"] ], [1,"Alice",697561200.0] ] ] ] Bobより後の誕生日は、Aliceだけなので正しく検索できていることがわかります。 範囲検索では、不等号(>,<,<=,>=)が使えます。 ○ geo_distance()関数で矩形近似により境界をまたぐ二点間の距離計算をサポート 今回のリリースでは、geo_distance()関数で子午線や日付変更線、赤道といった 境界をまたいだ場合での任意の二点間の距離計算をサポートしました。 距離の近似方法にはいくつかやりかたがあります。 groongaではgeo_distance関数において以下の近似方法をサポートしています。 それぞれ、速度や正確さにトレードオフが存在します。 * 矩形近似 http://groonga.org/ja/docs/reference/functions/geo_distance.html#rectangle 二点間の地形を平面とみなして計算します。 最も高速に距離を計算できますが、二点間の距離が離れると正確に計算できません。 * 球面近似 http://groonga.org/ja/docs/reference/functions/geo_distance.html#sphere 二点間の地形を球面とみなして計算します。 矩形近似より遅くなりますが、より正確に距離を計算できます。 * 楕円近似 http://groonga.org/ja/docs/reference/functions/geo_distance.html#ellipsoid 二点間の地形を楕円体とみなして計算します。 球面近似より遅くなりますが、より正確に距離を計算できます。 今回の機能追加は近似方法として矩形近似を選択した場合に有効です。 実際に、子午線をまたいで二点間の距離を計算するサンプルを紹介します。 以下のサンプルではパリ(フランス)からマドリード(スペイン)の距離を矩形近似で 計算しています。 "175904000x8464000"と表記されているのがパリ(フランス)のミリ秒表記で、 "145508000x-13291000"がマドリード(スペイン)のミリ秒表記です。 select Geo --output_columns distance --scorer 'distance = geo_distance("175904000x8464000", "145508000x-13291000", "rectangle")' [ [ 0, 1337566253.89858, 0.000355720520019531 ], [ [ [ 1 ], [ [ "distance", "Int32" ] ], [ 1051293 ] ] ] ] ある点の経緯度をどのようにミリ秒表記で表わすかについては、 以下の組み込み型に詳細を記載してあります。 http://groonga.org/ja/docs/reference/type.html geo_distance関数の詳しい使いかたについては以下のドキュメントを参照してください。 http://groonga.org/ja/docs/reference/functions/geo_distance.html ○ 変更点 さて、2.0.8からの変更点は以下の通りです。 http://groonga.org/ja/docs/news.html#release-2-0-9 2.0.9リリース - 2012/11/29 -------------------------- 改良 * geo_distance 関数の近似方法として rectangle を指定したときに 境界をまたいでも距離の算出できるようにした。 [#1534] * [doc] GQTP の仕様についてのドキュメントを追加した。 * groongaコマンドの起動時に致命的でない getaddrinfo() 関数のエラーは無視するようにした。 この変更はgroongaを通常使用する場合には影響しません。 その理由はデフォルトのホスト名が解決できるかチェックするのに使っていただけだからです。 * [実験的] キーワードとその周辺のテキストを抽出するための snippet_html() 関数を追加した。 * テーブルのレコードを出力している際に発生したエラーを表示するようにした。 * 複数のテーブルで関連したインデックスが設定されていれば、ネストしたインデックス (複数のカラムインデックス名を . で連結して指定)に対してキーワードで検索できるようにした。 * TokenMecab トークナイザを使ったときにログに"[tokenizer][mecab]"タグを出力するようにした。 * TokenKyTea トークナイザを使ったときにログに"[tokenizer][kytea]"タグを出力するようにした。 * 検索結果の内容のうち、コマンドのエラー表示は別の配列として表示するようにした。 この変更は非互換な変更ですが、既存のプログラムには影響しません。 * [doc] 出力形式 に関するドキュメントを追加。 * [doc] リターンコード に関するドキュメントを追加。 * インデックスを使った指定範囲の検索をサポート。 修正 * GQTPヘッダー にてステータスコードにネットワークバイトオーダーを使用するように修正した。 ネットワークプロトコルの慣習に合わせたものですが、これによりgroongaバージョン2.0.8以下のクライアントから groongaバージョン2.0.9以上のサーバに接続してコマンドの実行に失敗したときにバイトオーダーが異なるため、 ステータスコードを正しく表示できなくなります。 * UTF-8の正規化でオフセット計算の誤りを修正した。この変更は snippet_html() 関数の返す結果に影響し、 キーワードとタグ周辺のテキストが誤った位置に挿入されないようにします。 [#1531] [嶋田大貴さんが報告] * [windows] groongaコマンドの起動時にバッファの範囲外アクセスによるセグメンテーションフォルトが 発生しないように修正した。 [#1532] [Akio Tajimaさんがパッチ提供] * [windows] カラムに保存しているデータのサイズが128MBを超える場合に、 そのデータを参照できない不具合を修正した。 [groonga-dev,01088] [ongaeshiさんが報告] * Int* や UInt* ( Int32/Uint32 は除く) に対してカラムインデックスによる検索結果が正しくない不具合を修正した。 * 削除したはずのレコードが検索結果で見つかる問題を修正した。 * latin1やkoi8rの正規化で、与えた文字列データにNULL終端が途中に含まれていると すべての文字列データを正規化できない不具合を修正した。 * select コマンドでデータが保存されていないカラムを参照したときに、 型にあったデフォルト値を返さない不具合を修正した。 * 静的なインデックス構築方法でベクタ型のカラムのメタデータが含まれないようにした。 この変更は検索結果にメタデータが含まれないようにします。 感謝 * 嶋田 大貴さん * Akio Tajimaさん * ongaeshiさん -- HAYASHI Kentaro <hayas****@clear*****>