4.3. ストレージモード¶
ここでは Mroonga におけるストレージモードの利用方法を説明します。
4.3.1. 全文検索の利用方法¶
インストールが確認できたら、テーブルを1つ作成してみましょう。 ENGINE = Mroonga
とMroongaを指定するところがポイントです。:
mysql> CREATE TABLE diaries (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> content VARCHAR(255),
-> FULLTEXT INDEX (content)
-> ) ENGINE = Mroonga DEFAULT CHARSET utf8;
Query OK, 0 rows affected (0.10 sec)
INSERTでデータを投入してみましょう。
mysql> INSERT INTO diaries (content) VALUES ("It'll be fine tomorrow.");
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO diaries (content) VALUES ("It'll rain tomorrow");
Query OK, 1 row affected (0.00 sec)
全文検索を実行してみます。
mysql> SELECT * FROM diaries WHERE MATCH(content) AGAINST("fine");
+----+-----------------------------------------+
| id | content |
+----+-----------------------------------------+
| 1 | It'll be fine tomorrow. |
+----+-----------------------------------------+
1 row in set (0.00 sec)
おぉぉー。検索できましたね。
4.3.2. 検索スコアの取得方法¶
注釈
1.0.0以前のMroongaではMySQLの標準的な検索スコアの取得方法ではなく、 _score
という専用のカラムを作成するという独自の方法でした。1.0.0からはMySQLの標準的な取得方法になっています。
全文検索を行う際、指定したキーワードにより内容が一致するレコードを上位に表示したいというような場合があります。そうしたケースでは検索スコアを利用します。
検索スコアはMySQLの標準的な方法 [1] で取得できます。つまり、SELECTの取得するカラム名を指定するところやORDER BYのところにMATCH...AGAINSTを指定します。
それでは実際にやってみましょう。:
mysql> INSERT INTO diaries (content) VALUES ("It's fine today. It'll be fine tomorrow as well.");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO diaries (content) VALUES ("It's fine today. But it'll rain tomorrow.");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT *, MATCH (content) AGAINST ("fine") FROM diaries WHERE MATCH (content) AGAINST ("fine") ORDER BY MATCH (content) AGAINST ("fine") DESC;
+----+--------------------------------------------------------------+------------------------------------+
| id | content | MATCH (content) AGAINST ("fine") |
+----+--------------------------------------------------------------+------------------------------------+
| 3 | It's fine today. It'll be fine tomorrow as well. | 2 |
| 1 | It'll be fine tomorrow. | 1 |
| 4 | It's fine today. But it'll rain tomorrow. | 1 |
+----+--------------------------------------------------------------+------------------------------------+
3 rows in set (0.00 sec)
検索対象の文字列 晴れ
をより多く含む、すなわち検索スコアの高い id = 3
のメッセージが上に来ていることが確認できます。また、SELECT句にMATCH AGAINSTを記述しているため、検索スコアも取得できています。
属性名を変更したい場合は AS
を使って下さい。
mysql> SELECT *, MATCH (content) AGAINST ("fine") AS score FROM diaries WHERE MATCH (content) AGAINST ("fine") ORDER BY MATCH (content) AGAINST ("fine") DESC;
+----+--------------------------------------------------------------+-------+
| id | content | score |
+----+--------------------------------------------------------------+-------+
| 3 | It's fine today. It'll be fine tomorrow as well. | 2 |
| 1 | It'll be fine tomorrow. | 1 |
| 4 | It's fine today. But it'll rain tomorrow. | 1 |
+----+--------------------------------------------------------------+-------+
3 rows in set (0.00 sec)
4.3.3. 全文検索用パーサの変更¶
MySQLは全文検索用のパーサ [2] を指定する以下のような構文を持っています。:
FULLTEXT INDEX (content) WITH PARSER parser_name
しかし、この構文を利用する場合は、あらかじめすべてのパーサをMySQLに登録しておく必要があります。一方、Groongaはトークナイザー(MySQLでいうパーサ)を動的に追加することができます。そのため、Mroongaでもこの構文を採用するとGroonga側に動的に追加されたトークナイザーに対応できなくなります。Groongaに動的に追加されるトークナイザーにはMeCabを用いたトークナイザーもあり、この制限に縛られることは利便性を損なうと判断し、以下のようなコメントを用いた独自の構文を採用することにしました。:
FULLTEXT INDEX (content) COMMENT 'tokenizer "TokenMecab"'
注釈
FULLTEXT INDEX
に COMMENT
を指定できるのはMySQL 5.5からになります。MySQL 5.1を利用している場合は後述の mroonga_default_parser
変数を利用してください。
You can specify one of following values as the tokenizer.
- off
トークナイズしません。"off"は``content``をそのまま扱いたい場合に使います。例えば、この値は前方一致検索のために指定します。
- TokenBigram
バイグラムでトークナイズする。ただし、連続したアルファベット・連続した数字・連続した記号はそれぞれ1つのトークンとして扱う。そのため、3文字以上のトークンも存在する。これはノイズを減らすためである。
デフォルト値。
- TokenMecab
MeCabを用いてトークナイズする。groongaがMeCabサポート付きでビルドされている必要がある。
- TokenBigramSplitSymbol
バイグラムでトークナイズする。TokenBigramと異なり、記号が連続していても特別扱いして1つのトークンとして扱わず通常のバイグラムの処理を行う。
TokenBigramではなくTokenBigramSplitSymbolを利用すると「Is it really!?!?!?」の「!?!?!?」の部分に「!?」でマッチする。TokenBigramの場合は「!?!?!?」でないとマッチしない。
- TokenBigramSplitSymbolAlpha
バイグラムでトークナイズする。TokenBigramSplitSymbolに加えて、連続したアルファベットも特別扱いせずに通常のバイグラムの処理を行う。
TokenBigramではなくTokenBigramSplitSymbolAlphaを利用すると「Is it really?」に「real」でマッチする。TokenBigramの場合は「really」でないとマッチしない。
- TokenBigramSplitSymbolAlphaDigit
バイグラムでトークナイズする。TokenBigramSplitSymbolAlphaに加えて、連続した数字も特別扱いせずに通常のバイグラムの処理を行う。つまり、すべての字種を特別扱いせずにバイグラムの処理を行う。
TokenBigramではなくTokenBigramSplitSymbolAlphaDigitを利用すると「090-0123-4567」に「567」でマッチする。TokenBigramの場合は「4567」でないとマッチしない。
- TokenBigramIgnoreBlank
バイグラムでトークナイズする。TokenBigramと異なり、空白を無視して処理する。
TokenBigramではなくTokenBigramIgnoreBlankを利用すると「み な さ ん 注 目」に「みなさん」でマッチする。TokenBigramの場合は「み な さ ん」でないとマッチしない。
- TokenBigramIgnoreBlankSplitSymbol
バイグラムでトークナイズする。TokenBigramSplitSymbolと異なり、空白を無視して処理する。
TokenBigramSplitSymbolではなくTokenBigramIgnoreBlankSplitSymbolを利用すると「! !? ??」に「???」でマッチする。TokenBigramSplitSymbolの場合は「? ??」でないとマッチしない。
- TokenBigramIgnoreBlankSplitSymbolAlpha
バイグラムでトークナイズする。TokenBigramSplitSymbolAlphaと異なり、空白を無視して処理する。
TokenBigramSplitSymbolAlphaではなくTokenBigramIgnoreBlankSplitSymbolAlphaを利用すると「I am a pen.」に「ama」でマッチする。TokenBigramSplitSymbolAlphaの場合は「am a」でないとマッチしない。
- TokenBigramIgnoreBlankSplitSymbolAlphaDigit
バイグラムでトークナイズする。TokenBigramSplitSymbolAlphaDigitと異なり、空白を無視して処理する。
okenBigramSplitSymbolAlphaDigitではなくTokenBigramIgnoreBlankSplitSymbolAlphaDigitを利用すると「090 0123 4567」に「9001」でマッチする。TokenBigramSplitSymbolAlphaDigitの場合は「90 01」でないとマッチしない。
- TokenDelimit
空白区切りでトークナイズする。
「movie horror topic」をトークナイズすると「movie」、「horror」、「topic」になります。
- TokenDelimitNull
null文字(\0)区切りでトークナイズする。
「movie\0horror\0topic」をトークナイズすると「movie」、「horror」、「topic」になります。
- TokenUnigram
ユニグラムでトークナイズする。ただし、連続したアルファベット・連続した数字・連続した記号はそれぞれ1つのトークンとして扱う。そのため、2文字以上のトークンも存在する。これはノイズを減らすためである。
- TokenTrigram
トリグラムでトークナイズする。ただし、連続したアルファベット・連続した数字・連続した記号はそれぞれ1つのトークンとして扱う。そのため、4文字以上のトークンも存在する。これはノイズを減らすためである。
You can specify the default parser by passing --with-default-tokenizer
option in configure
when you build mroonga
./configure --with-default-tokenizer TokenMecab ...
Or you can set mroonga_default_tokenizer
variable in my.cnf or by SQL. If you specify it in my.cnf, the change will not be lost after restarting MySQL, but you need to restart MySQL to make it effective. On the other hand, if you set it in SQL, the change is effective immediately, but it will be lost when you restart MySQL.
my.cnf:
[mysqld]
mroonga_default_tokenizer=TokenMecab
SQL:
mysql> SET GLOBAL mroonga_default_tokenizer = TokenMecab;
Query OK, 0 rows affected (0.00 sec)
4.3.4. ノーマライザーの指定方法¶
Mroongaは、文書のエンコーディング(照合順序)に応じたノーマライザーを使用します。これはテキストをトークナイズするときとテーブルのキーを保存するときに使われます。
utf8_general_ci
または utf8mb4_general_ci
の場合、NormalizerMySQLGeneralCI
ノーマライザーが使用されます。
utf8_unicode_ci
または utf8mb4_unicode_ci
の場合、NormalizerMySQLUnicodeCI
ノーマライザーが使用されます。
utf8_bin
の場合、ノーマライザーは使用されません。
以下は、 utf8_unicode_ci
の照合順序を指定して NormalizerMySQLUnicodeCI
ノーマライザーを使用する例です。:
mysql> SET NAMES utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE diaries (
-> day DATE PRIMARY KEY,
-> content VARCHAR(64) NOT NULL,
-> FULLTEXT INDEX (content)
-> ) Engine=Mroonga DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.18 sec)
mysql> INSERT INTO diaries VALUES ("2013-04-23", "ブラックコーヒーを飲んだ。");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM diaries
-> WHERE MATCH (content) AGAINST ("+ふらつく" IN BOOLEAN MODE);
+------------+-----------------------------------------+
| day | content |
+------------+-----------------------------------------+
| 2013-04-23 | ブラックコーヒーを飲んだ。 |
+------------+-----------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM diaries
-> WHERE MATCH (content) AGAINST ("+ブラック" IN BOOLEAN MODE);
+------------+-----------------------------------------+
| day | content |
+------------+-----------------------------------------+
| 2013-04-23 | ブラックコーヒーを飲んだ。 |
+------------+-----------------------------------------+
1 row in set (0.00 sec)
Mroongaは、Groongaのノーマライザーを指定する以下のような構文を持っています。:
FULLTEXT INDEX (content) COMMENT 'normalizer "NormalizerAuto"'
Groongaのノーマライザーの詳細については Groongaのドキュメント を参照してください。
以下は、NormalizerAuto
のノーマライザーを使用する例です。:
mysql> SET NAMES utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE diaries (
-> day DATE PRIMARY KEY,
-> content VARCHAR(64) NOT NULL,
-> FULLTEXT INDEX (content) COMMENT 'normalizer "NormalizerAuto"'
-> ) Engine=Mroonga DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.19 sec)
mysql> INSERT INTO diaries VALUES ("2013-04-23", "ブラックコーヒーを飲んだ。");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM diaries
-> WHERE MATCH (content) AGAINST ("+ふらつく" IN BOOLEAN MODE);
Empty set (0.00 sec)
mysql> SELECT * FROM diaries
-> WHERE MATCH (content) AGAINST ("+ブラック" IN BOOLEAN MODE);
+------------+-----------------------------------------+
| day | content |
+------------+-----------------------------------------+
| 2013-04-23 | ブラックコーヒーを飲んだ。 |
+------------+-----------------------------------------+
1 row in set (0.00 sec)
4.3.5. トークンフィルターの指定方法¶
Mroongaは、Groongaのトークンフィルターを指定する以下のような構文を持っています。:
FULLTEXT INDEX (content) COMMENT 'token_filters "TokenFilterStem"'
以下は、TokenFilterStem
のトークンフィルターを使用する例です。:
mysql> SELECT mroonga_command('register token_filters/stem');
+------------------------------------------------+
| mroonga_command('register token_filters/stem') |
+------------------------------------------------+
| true |
+------------------------------------------------+
1 row in set (0.00 sec)
mysql> CREATE TABLE memos (
-> id INT NOT NULL PRIMARY KEY,
-> content TEXT NOT NULL,
-> FULLTEXT INDEX (content) COMMENT 'normalizer "NormalizerAuto", token_filters "TokenFilterStem"'
-> ) Engine=Mroonga DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.18 sec)
mysql> INSERT INTO memos VALUES (1, "I develop Groonga");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (2, "I'm developing Groonga");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (3, "I developed Groonga");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM memos
-> WHERE MATCH (content) AGAINST ("+develops" IN BOOLEAN MODE);
+----+------------------------+
| id | content |
+----+------------------------+
| 1 | I develop Groonga |
| 2 | I'm developing Groonga |
| 3 | I developed Groonga |
+----+------------------------+
3 rows in set (0.01 sec)
Groongaのトークンフィルターの詳細については Groongaのドキュメント を参照してください。
以下は、TokenFilterStopWord
のトークンフィルターを使用する例です。:
mysql> SELECT mroonga_command("register token_filters/stop_word");
+-----------------------------------------------------+
| mroonga_command("register token_filters/stop_word") |
+-----------------------------------------------------+
| true |
+-----------------------------------------------------+
1 row in set (0.00 sec)
mysql> CREATE TABLE terms (
-> term VARCHAR(64) NOT NULL PRIMARY KEY,
-> is_stop_word BOOL NOT NULL
-> ) Engine=Mroonga COMMENT='default_tokenizer "TokenBigram", token_filters "TokenFilterStopWord"' DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.12 sec)
mysql> CREATE TABLE memos (
-> id INT NOT NULL PRIMARY KEY,
-> content TEXT NOT NULL,
-> FULLTEXT INDEX (content) COMMENT 'table "terms"'
-> ) Engine=Mroonga DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.17 sec)
mysql>
mysql> INSERT INTO terms VALUES ("and", true);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (1, "Hello");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (2, "Hello and Good-bye");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (3, "Good-bye");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM memos
-> WHERE MATCH (content) AGAINST ("+\"Hello and\"" IN BOOLEAN MODE);
+----+--------------------+
| id | content |
+----+--------------------+
| 1 | Hello |
| 2 | Hello and Good-bye |
+----+--------------------+
2 rows in set (0.01 sec)
これは、全文検索用の語彙表テーブルを指定する方法を使用しています。
4.3.6. Groongaのカラムフラグの指定方法¶
Mroongaは、Groongaのカラムフラグを指定する以下のような構文を持っています。:
content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
以下は、COMPRESS_ZLIB
フラグを使用する例です。:
mysql> CREATE TABLE entries (
-> id INT UNSIGNED PRIMARY KEY,
-> content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
-> ) Engine=Mroonga DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.12 sec)
Groongaのカラムフラグの詳細については Groongaのドキュメント を参照してください。
4.3.7. 位置情報検索の利用方法¶
ストレージモードでは全文検索だけではなく位置情報検索も高速に実行できます。ただし、MyISAMとは異なりデータとして格納できるのはPOINT型のみです。LINEなどの他のデータ型は保存できません。また、インデックスを用いた高速な検索に対応しているのはMBRContainsだけです。MBRDisjointなどには対応していません。
位置情報検索を利用する場合のテーブル定義はMyISAMと同様にPOINT型のカラムを定義し、そのカラムに対してSPATIAL INDEXを指定します。:
mysql> CREATE TABLE shops (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(255),
-> location POINT NOT NULL,
-> SPATIAL INDEX (location)
-> ) ENGINE = Mroonga;
Query OK, 0 rows affected (0.06 sec)
データの登録方法もMyISAMのときと同様にGeomFromText()関数を使って文字列からPOINT型の値を作成します。:
mysql> INSERT INTO shops VALUES (null, 'Nezu\'s Taiyaki', GeomFromText('POINT(139.762573 35.720253)'));
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO shops VALUES (null, 'Naniwaya', GeomFromText('POINT(139.796234 35.730061)'));
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO shops VALUES (null, 'Yanagiya Taiyaki', GeomFromText('POINT(139.783981 35.685341)'));
Query OK, 1 row affected (0.00 sec)
池袋駅(139.7101 35.7292)が左上の点、東京駅(139.7662 35.6815)が右下の点となるような長方形内にあるお店を探す場合は以下のようなSELECTになります。:
mysql> SELECT id, name, AsText(location) FROM shops WHERE MBRContains(GeomFromText('LineString(139.7101 35.7292, 139.7662 35.6815)'), location);
+----+-----------------------+------------------------------------------+
| id | name | AsText(location) |
+----+-----------------------+------------------------------------------+
| 1 | Nezu's Taiyaki | POINT(139.762572777778 35.7202527777778) |
+----+-----------------------+------------------------------------------+
1 row in set (0.00 sec)
位置情報で検索できていますね!
4.3.8. レコードIDの取得方法¶
Groongaではテーブルにレコードを追加した際にレコードを一意に識別するための番号が割当てられます。
Mroongaではアプリケーションの開発を容易にするため、このレコードIDをSQLで取得できるようになっています。
レコードIDを取得するためには、テーブル定義時に _id
という名前のカラムを作成して下さい。
mysql> CREATE TABLE memos (
-> _id INT,
> content VARCHAR(255),
-> UNIQUE KEY (_id) USING HASH
-> ) ENGINE = Mroonga;
Query OK, 0 rows affected (0.04 sec)
_idカラムのデータ型は整数型(TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT)である必要があります。
また_idカラムにはインデックスを作成することが可能ですが、HASH形式である必要があります。
INSERTでテーブルにレコードを追加してみましょう。_idカラムは仮想カラムとして実装されており、また_idの値であるレコードIDはGroongaにより割当てられるため、SQLによる更新時に値を指定することはできません。更新対象から外すか、値に null
を使用する必要があります。
mysql> INSERT INTO memos VALUES (null, "Saury for today's dinner.");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (null, "Update mroonga tomorrow.");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (null, "Buy some dumpling on the way home.");
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO memos VALUES (null, "Thank God It's meat day.");
Query OK, 1 row affected (0.00 sec)
レコードIDを取得するには、_idカラムを含むようにしてSELECTを行います。
mysql> SELECT * FROM memos;
+------+------------------------------------------+
| _id | content |
+------+------------------------------------------+
| 1 | Saury for today's dinner. |
| 2 | Update mroonga tomorrow. |
| 3 | Buy some dumpling on the way home. |
| 4 | Thank God It's meat day. |
+------+------------------------------------------+
4 rows in set (0.00 sec)
また直前のINSERTにより割当てられたレコードIDについては、last_insert_grn_id関数により取得することもできます。
mysql> INSERT INTO memos VALUES (null, "Just one bottle of milk in the fridge.");
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_grn_id();
+----------------------+
| last_insert_grn_id() |
+----------------------+
| 5 |
+----------------------+
1 row in set (0.00 sec)
last_insert_grn_id関数はユーザ定義関数(UDF)としてMroongaに含まれていますが、インストール時にCREATE FUNCTIONでMySQLに追加していない場合には、以下の関数定義DDLを実行しておく必要があります。
mysql> CREATE FUNCTION last_insert_grn_id RETURNS INTEGER SONAME 'ha_mroonga.so';
ご覧のように_idカラムやlast_insert_grn_id関数を通じてレコードIDを取得することができました。ここで取得したレコードIDは後続のUPDATEなどのSQL文で利用すると便利です。
mysql> UPDATE memos SET content = "So much milk in the fridge." WHERE _id = last_insert_grn_id();
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
4.3.9. スニペット(キーワード周辺のテキスト)の取得方法¶
Mroongaは周辺テキスト付きでキーワードを取得する機能を提供しています。この機能は mroonga_snippet() UDFとして実装されています。
4.3.10. Groongaコマンドの実行方法¶
ストレージモードではMroongaはすべてのデータをGroongaのデータベースに保存します。Mroongaを使うことでSQLでGroongaのデータベースにアクセスできるようになります。SQLはとても強力ですが、ファセット検索などのようないくつかの操作が得意ではありません。
最近ではファセット検索は一般的なものになりました。amazon.comやebay.comのように多くのオンラインショッピングサイトがファセット検索をサポートしています。ファセット検索はユーザが検索結果を絞り込む前に絞り込み検索をし、その絞り込み検索の結果を表示します。ユーザは絞りこまれた結果から自分が探しているものを選ぶだけです。ファセット検索を使うとユーザは以下のようなメリットがあります。
ユーザはどうやって検索結果を絞り込むかを考える必要はありません。単に表示された絞り込み結果から選ぶだけです。
ユーザは「見つかりませんでした」ページを見ることがありません。ファセット検索では絞り込んだ結果のうち、ヒットする項目がある結果だけを表示します。
絞り込み検索は検索結果に対して複数の GROUP BY 操作を実行する必要があります。SQLでファセット検索をやろうとすると、複数の SELECT リクエストが必要になります。これは効率的ではありません。
Groongaは1回のgroongaコマンドでファセット検索をできます。これは効率的です。Groongaには select コマンドというファセット検索に対応した検索コマンドがあります。Groongaではファセット検索は ドリルダウン(drilldown) と呼ばれています。Groongaの select コマンドの詳細については Groongaのドキュメント を参照してください。
mroongaは mroonga_command() 関数を提供しています。この関数を使えばSQLの中で好きなgroongaコマンドを実行できます。しかし、使うのは select コマンドだけにしておくべきです。スキーマやデータを変更するコマンドを使うと一貫性が壊れてしまうかもしれません。
実行例で使用するスキーマ定義はこちら:
CREATE TABLE diaries (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(255),
date DATE,
year YEAR,
`year_month` VARCHAR(9),
tag VARCHAR(32),
FULLTEXT INDEX (content)
) ENGINE = Mroonga DEFAULT CHARSET utf8;
実行例で使用するサンプルデータはこちら:
INSERT INTO diaries (content, date, year, `year_month`, tag)
VALUES ('Groonga is an open-source fulltext search engine and column store.',
'2013-04-08',
'2013',
'2013-04',
'groonga');
INSERT INTO diaries (content, date, year, `year_month`, tag)
VALUES ('Mroonga is an open-source storage engine for fast fulltext search with MySQL.',
'2013-04-09',
'2013',
'2013-04',
'MySQL');
INSERT INTO diaries (content, date, year, `year_month`, tag)
VALUES ('Tritonn is a patched version of MySQL that supports better fulltext search function with Senna.',
'2013-03-29',
'2013',
'2013-03',
'MySQL');
各レコードは tag として groonga と MySQL が付いています。各レコードは year と year_month も持っています。ファセット検索のキーとして tag 、 year 、 year_month を使えます。
Groongaはファセット検索のことをドリルダウンと呼んでいます。そのため、Groongaでのパラメータ名は --drilldown となっています。groongaは検索結果をJSONで返します。そのため、 mroonga_command() も検索結果をJSONで返します。これはSQLらしくありません。JSON形式の検索結果は自分でパースしないといけません。
以下は利用可能なファセット検索キーをすべて使った例です。(結果のJSONは整形済み):
SELECT mroonga_command("select diaries --output_columns _id --limit 0 --drilldown tag,year,year_month") AS faceted_result;
+-----------------------------+
| faceted_result |
+-----------------------------+
| [[[3], |
| [["_id","UInt32"]]], |
| [[2], |
| [["_key","ShortText"], |
| ["_nsubrecs","Int32"]], |
| ["groonga",1], |
| ["MySQL",2]], |
| [[1], |
| [["_key","Time"], |
| ["_nsubrecs","Int32"]], |
| [1356998400.0,3]], |
| [[2], |
| [["_key","ShortText"], |
| ["_nsubrecs","Int32"]], |
| ["2013-04",2], |
| ["2013-03",1]]] |
+-----------------------------+
1 row in set (0.00 sec)
詳細は Groongaのselectコマンドのドキュメント を確認してください。
4.3.11. ログ出力¶
Mroongaではデフォルトでログの出力を行うようになっています。
ログファイルはMySQLのデータディレクトリ直下に groonga.log
というファイル名で出力されます。
以下はログの出力例です。
2010-10-07 17:32:39.209379|n|b1858f80|mroonga 1.10 started.
2010-10-07 17:32:44.934048|d|46953940|hash get not found (key=test)
2010-10-07 17:32:44.936113|d|46953940|hash put (key=test)
ログのデフォルトの出力レベルはNOTICE(必要な情報のみ出力。デバッグ情報などは出力しない)となっております。
ログの出力レベルは mroonga_log_level
というシステム変数で確認することができます(グローバル変数)。またSET文で動的に出力レベルを変更することもできます。
mysql> SHOW VARIABLES LIKE 'mroonga_log_level';
+-------------------+--------+
| Variable_name | Value |
+-------------------+--------+
| mroonga_log_level | NOTICE |
+-------------------+--------+
1 row in set (0.00 sec)
mysql> SET GLOBAL mroonga_log_level=DUMP;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE 'mroonga_log_level';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| mroonga_log_level | DUMP |
+-------------------+-------+
1 row in set (0.00 sec)
設定可能なログレベルは以下の通りです。
- NONE
- EMERG
- ALERT
- CRIT
- ERROR
- WARNING
- NOTICE
- INFO
- DEBUG
- DUMP
詳細は mroonga_log_level を参照してください。
またFLUSH LOGSでログの再オープンを行うことができます。MySQLサーバを停止せずにログのローテートを行いたいような場合には、以下の手順で実行すると良いでしょう。
groonga.log
ファイルの名前を変更(OSコマンドのmvなどで)MySQLサーバに対して"FLUSH LOGS"を実行(mysqlコマンドあるいはmysqladminコマンドにて)