いよいよ、gihyo.jpさんでgroongaの隔週更新連載が始まりました!!
第4回の記事も公開されたので、一読をおすすめします。
- 「第1回 全文検索エンジンgroongaを紹介します!」
- 「第2回 groongaをRuby On Railsでも使ってみた ~chikamap.comの事例から」
- 「第3回 すべてのMySQLユーザに高速な全文検索機能を! - mroongaの紹介」
- 「第4回 rroongaを使ったソースコード検索エンジンMilkode」
連載は始まりましたが、利用事例をどんどん紹介していきたいです。(利用事例のストックが尽きたら終了してしまいます。)
groongaやmroonga、rroongaを実際に使っていて利用事例記事を書いてもいいよ、という人をまだまだ募集しています。
詳細はgroonga普及のための協力のお願いを参照してください。
はじめに
MySQLで高速に全文検索するためのオープンソースのストレージエンジンとしてmroongaを公開しています。
最新のバージョンは2013年5月29日にリリースした3.04です。
今回は、mroongaでカラムごとに重み付けして検索する方法を紹介します。
重み付けと全文検索
例えば、本にコメントをつけているときのことを考えてみましょう。
books
テーブルがあって、books
テーブルにはタイトルを保持する title
カラムとコメントを記録するための comment
カラムがあるとします。
サンプルのスキーマ定義は以下のようになるでしょう。
CREATE TABLE books (
`id` INTEGER AUTO_INCREMENT,
`title` text,
`comment` text,
PRIMARY KEY(`id`),
FULLTEXT INDEX content_index (title, comment)
) engine=mroonga default charset utf8;
上記サンプルのためのサンプルデータを用意します。
INSERT INTO books (title, comment) VALUES ('[groonga入門]', 'groongaの初歩的な内容のみ。');
INSERT INTO books (title, comment) VALUES ('[mroonga入門]', 'mroongaの初歩的な内容のみ。groongaについても触れている。');
INSERT INTO books (title, comment) VALUES ('[実践groonga - groonga入門の次のステップ]', '入門を卒業したら読む本。');
INSERT INTO books (title, comment) VALUES ('[実践rroonga]', '入門の次に読むべき本。すぐに使える実践的な内容が売り。');
INSERT INTO books (title, comment) VALUES ('[mroongaのレシピ]', '入門の次に読むべき実践的な本');
INSERT INTO books (title, comment) VALUES ('[groongaのレシピ]', 'いわゆるレシピブック。');
title
もしくはcomment
カラムからgroongaを検索してみましょう。
SELECT * FROM books WHERE
MATCH (title,comment) AGAINST ('+groonga' IN BOOLEAN MODE) ORDER BY
MATCH (title,comment) AGAINST ('+groonga' IN BOOLEAN MODE) DESC;
この結果は以下のようになります。
id title comment
1 [groonga入門] groongaの初歩的な内容のみ。
3 [実践groonga - groonga入門の次のステップ] 入門を卒業したら読む本。
2 [mroonga入門] mroongaの初歩的な内容のみ。groongaについても触れている。
6 [groongaのレシピ] いわゆるレシピブック。
確かにgroonga
を含むものを検索できているのですが、[mroonga入門]
が[groongaのレシピ]
よりも上位になっています。
groongaを主に検索したい場合はこれではあまり嬉しくありません。
title
カラムの内容を重視して検索することはできないでしょうか。
3.04以前でもtitle
カラムを重視して検索することは、実はできます。
MATCH (column) AGAINST(...) * (重み付けの値)
をクエリに指定してあげればいいのです。
そこで、次のようなクエリを試してみたくなったかも知れません。
SELECT * FROM books WHERE
MATCH (title,comment) AGAINST('+groonga' IN BOOLEAN MODE) ORDER BY
MATCH (title) AGAINST('+groonga' IN BOOLEAN MODE) * 10 DESC, MATCH(comment) AGAINST('+groonga' IN BOOLEAN MODE) DESC;
でも、実際に試してみると、以下のような結果になります。なんだかもっと意図しない結果になってしまっています。
id title comment
1 [groonga入門] groongaの初歩的な内容のみ。
2 [mroonga入門] mroongaの初歩的な内容のみ。groongaについても触れている。
3 [実践groonga - groonga入門の次のステップ] 入門を卒業したら読む本。
6 [groongaのレシピ] いわゆるレシピブック。
これは、title
カラム、comment
カラムにインデックスを張っていなかったからでした。
インデックスを張るようにスキーマを修正しないといけません。例えば以下のようにします。
FULLTEXT INDEX title_index (title),
FULLTEXT INDEX comment_index (comment),
FULLTEXT INDEX content_index (title, comment)
個別にインデックスを張るようにしてから、さきほどのクエリを再度実行してみましょう。
以下のようにtitle
をより重視して検索できていることがわかります。
id title comment
3 [実践groonga - groonga入門の次のステップ] 入門を卒業したら読む本。
1 [groonga入門] groongaの初歩的な内容のみ。
6 [groongaのレシピ] いわゆるレシピブック。
2 [mroonga入門] mroongaの初歩的な内容のみ。groongaについても触れている。
でも、このためだけにカラムごとにインデックスを張っておかないといけないのはなんだか無駄ですね。
良い方法はないでしょうか。
Wプラグマとは
mroonga 3.04では 'W'プラグマというものがサポートされました。
'W'プラグマというのは Tritonnに由来するマルチカラムインデックスのセクションごとに重み付けを指定するための書式です。
'W'プラグマの書式は以下の通りです。
*W[数値[:重み][,数値[:重み]]...
では、'W'プラグマを使って検索してみましょう。
title
カラムに重み10を与え、comment
カラムに重み1を与えるクエリは以下のようになります。
Mroonga 3.11まではこうなります。
SELECT * FROM books WHERE
MATCH (title,comment) AGAINST('*W0:10,1:1 +groonga' IN BOOLEAN MODE) ORDER BY
MATCH (title,comment) AGAINST('*W0:10,1:1 +groonga' IN BOOLEAN MODE) DESC;
Mroonga 3.12以降(セクションの指定はTritonn同様に1オリジンになりました。)だとこうなります。
SELECT * FROM books WHERE
MATCH (title,comment) AGAINST('*W1:10,2:1 +groonga' IN BOOLEAN MODE) ORDER BY
MATCH (title,comment) AGAINST('*W1:10,2:1 +groonga' IN BOOLEAN MODE) DESC;
'W'プラグマを使う場合、title
やcomment
カラムごとにインデックスを張る必要はありません。
最初のスキーマで指定したマルチカラムインデックスさえあれば十分です。
クエリの実行結果は以下のようになります。
id title comment
3 [実践groonga - groonga入門の次のステップ] 入門を卒業したら読む本。
1 [groonga入門] groongaの初歩的な内容のみ。
6 [groongaのレシピ] いわゆるレシピブック。
2 [mroonga入門] mroongaの初歩的な内容のみ。groongaについても触れている。
個別のカラムにインデックスを張ったとき同様の結果がマルチカラムインデックスのみでも得られました。
まとめ
今回は、mroongaでカラムごとに重み付けして検索する方法を紹介しました。
mroongaに興味を持ったなら、まずはインストールして試してみてください。
mroongaの基本的な動作を知るためのユーザガイドもあります。インストールしたら試してみてください。