インデックス作成時に指定可能なフラグにSPLIT系を追加
SPLIT_ALPHA、SPLIT_DIGIT、SPLIT_SYMBOLという3つのSennaインデックス作成用フラグをUSING句で使えるようにしました。
これらのフラグはSenna本体では以前からサポートしていたのですが、これまではMySQLのDDL経由で指定することができませんでした。今回の対応によりMySQLからも指定可能となります。
この変更はsourceforgeのレポジトリに既にcommitしています(rev16)。特に問題がなければtritonn-1.0.5にて正式に導入するつもりです。
これを使うと何が便利になるの?
以下のようなINSERT文でNGRAMで作ったインデックスに1レコード追加したとします。
insert into t1 values ("FedoraCore500の技");
このときSPLIT系フラグが指定されていないと、以下のSELECT文では上記レコードをヒットさせることができません。
SELECT * FROM t1 WHERE MATCH(c1) AGAINST("00"); SELECT * FROM t1 WHERE MATCH(c1) AGAINST("Core");
この検索漏れは、NO NORMALIZEを指定することで回避できますが、NO NORMALIZEを使うと今度は以下のSELECT文でレコードをヒットさせることができなくなります。
SELECT * FROM t1 WHERE MATCH(c1) AGAINST("500");
これはUnicode正規化の機能をOFFにしてしまったためです。
こんな時、SPLIT系のフラグを指定してインデックスを作成しておくと上記全てのパタンでレコードをヒットさせることができます。
実行例
以下、実行例です。
[test] > create table t1 (c1 text, fulltext index ft -> using ngram, split_alpha, split_digit, split_symbol (c1)) -> default charset utf8 engine = myisam; Query OK, 0 rows affected (0.01 sec) [test] > show senna status\G *************************** 1. row *************************** Table: t1 Key_name: ft Column_name: c1 Encoding: utf8 Index_type: NGRAM Sectionalize: OFF Normalize: ON Split_alpha: ON Split_digit: ON Split_symbol: ON Initial_n_segments: 512 Senna_keys_size: 0 Senna_keys_file_size: 4268032 Senna_lexicon_size: 0 Senna_lexicon_file_size: 4268032 Senna_inv_seg_size: 167936 Senna_inv_chunk_size: 135168 1 row in set (0.00 sec) [test] > insert into t1 values ("FedoraCore500の技"); Query OK, 1 row affected (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("500"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("00"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("Core"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("Fedo"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("50"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec) [test] > SELECT * FROM t1 WHERE MATCH(c1) AGAINST("500"); +---------------------+ | c1 | +---------------------+ | FedoraCore500の技 | +---------------------+ 1 row in set (0.00 sec)