search
LoginSignup
15

More than 5 years have passed since last update.

posted at

updated at

mroongaでカラムごとに重み付けして検索するには

いよいよ、gihyo.jpさんでgroongaの隔週更新連載が始まりました!!
第4回の記事も公開されたので、一読をおすすめします。

連載は始まりましたが、利用事例をどんどん紹介していきたいです。(利用事例のストックが尽きたら終了してしまいます。)
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'プラグマを使う場合、titlecommentカラムごとにインデックスを張る必要はありません。
最初のスキーマで指定したマルチカラムインデックスさえあれば十分です。

クエリの実行結果は以下のようになります。

id  title   comment
3   [実践groonga - groonga入門の次のステップ]    入門を卒業したら読む本。
1   [groonga入門] groongaの初歩的な内容のみ。
6   [groongaのレシピ]   いわゆるレシピブック。
2   [mroonga入門] mroongaの初歩的な内容のみ。groongaについても触れている。

個別のカラムにインデックスを張ったとき同様の結果がマルチカラムインデックスのみでも得られました。

まとめ

今回は、mroongaでカラムごとに重み付けして検索する方法を紹介しました。

mroongaに興味を持ったなら、まずはインストールして試してみてください。

mroongaの基本的な動作を知るためのユーザガイドもあります。インストールしたら試してみてください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
15