Mattermost 2.1.0が2016/03/16にリリースされました。
@yuya-ocによるelectron製クライアントが公式採用されたり、公式ブログにどっかで見たような画面が出てきたり、"If anyone is interested in working on a Japanese translation, or other language translations, please join in the discussion." と絶賛日本語ローカライズしてくれる人大募集中らしくていろいろアツい感じです。
で、日本語検索が動かなかったのが今更気になったので軽く追ってみたところ、インデックス貼るだけで対応できそうだったので展開させていただきます。
皆様の世知辛いMattermost生活の一助になれば幸いです。
追伸: 2016/03/28
既出でした。。。 Cannot search CJK contents · Issue #2033 · mattermost/platform
概要
こちらでわかりやすくまとめられておりますが、簡単に検索に関する部分だけ。
Mattermost の検索機能 - Qiita
検索SQL組み立て
- Postgres
- MySQL
全文検索インデックス作成
- Postgres
- MySQL
どちらも各RDBMSの標準的な全文検索を使っているだけのようです。
特にMySQL側は、5.7から標準で対応しているngramパーサでインデックスを貼り直せば簡単にそのまま動きそうです。
参考: MySQL ngram全文検索パーサ
- まだ日本語全文検索で消耗してるの? - Qiita
- InnoDB 全文検索 : N-gram Parser | MySQL Server Blog
- MySQL :: MySQL 5.7 Reference Manual :: 12.9.8 ngram Full-Text Parser
対応方針
- RDBMSをMySQL 5.7.xに変更
- FULLTEXT Indexの貼り直し
RDBMSをMySQL 5.7.xに変更
Vagrantの動作サンプルをMySQL 5.7.xを使うように修正しました。(Postgresqlでも引き続き使えます)
Mattermost Sample for Vagrant (VirtualBox + CentOS 7.2.x)
my.cnf設定
Mattermostの文字コードがutf8mb4
なので、ラージインデックス設定を入れてあります。
あと、DB接続文字列を公式サンプルそのままにするためにvalidate_passwordプラグインを殺しておきました。
本運用する場合はその他のパラメータ含め、適宜設定してください。
[mysql]
default-character-set = utf8mb4
[mysqld]
# setting for utf8mb4
character-set-server = utf8mb4
innodb_large_prefix = ON
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda
# for test-env setting (DO NOT USE PRODUCTION!!)
validate_password=OFF
インデックス貼り直し
スキーマ確認
$ mysqldump -d mattermost -u mmuser -pmmuser_password > ddl.sql
$ grep "FULLTEXT" ddl.sql
FULLTEXT KEY `idx_posts_message_txt` (`Message`),
FULLTEXT KEY `idx_posts_hashtags_txt` (`Hashtags`)
CREATE TABLE `Posts` (
`Id` varchar(26) NOT NULL,
`CreateAt` bigint(20) DEFAULT NULL,
`UpdateAt` bigint(20) DEFAULT NULL,
`DeleteAt` bigint(20) DEFAULT NULL,
`UserId` varchar(26) DEFAULT NULL,
`ChannelId` varchar(26) DEFAULT NULL,
`RootId` varchar(26) DEFAULT NULL,
`ParentId` varchar(26) DEFAULT NULL,
`OriginalId` varchar(255) DEFAULT NULL,
`Message` text,
`Type` varchar(26) DEFAULT NULL,
`Props` text,
`Hashtags` text,
`Filenames` text,
PRIMARY KEY (`Id`),
KEY `idx_posts_update_at` (`UpdateAt`),
KEY `idx_posts_create_at` (`CreateAt`),
KEY `idx_posts_channel_id` (`ChannelId`),
KEY `idx_posts_root_id` (`RootId`),
FULLTEXT KEY `idx_posts_message_txt` (`Message`),
FULLTEXT KEY `idx_posts_hashtags_txt` (`Hashtags`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
FULLTEXTってPostsのメッセージとハッシュタグ(twitterみたいに #タグ
を付与できる機能)しかないんですね。
ハッシュタグの方は完全一致のほうがいいと思うので、そのままにしておきます。
ngramインデックスで貼り直し
既存のインデックスを落として、新しくngramを指定して貼り直します。
$ mysql mattermost -u mmuser -pmmuser_password
mysql> ALTER TABLE Posts DROP INDEX idx_posts_message_txt;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE Posts ADD FULLTEXT INDEX idx_posts_message_txt (`Message`) WITH PARSER ngram COMMENT 'ngram index sample';
Query OK, 0 rows affected (0.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from Posts;
+-------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--------------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--------------------+
| Posts | 0 | PRIMARY | 1 | Id | A | 5 | NULL | NULL | | BTREE | | |
| Posts | 1 | idx_posts_update_at | 1 | UpdateAt | A | 5 | NULL | NULL | YES | BTREE | | |
| Posts | 1 | idx_posts_create_at | 1 | CreateAt | A | 5 | NULL | NULL | YES | BTREE | | |
| Posts | 1 | idx_posts_channel_id | 1 | ChannelId | A | 1 | NULL | NULL | YES | BTREE | | |
| Posts | 1 | idx_posts_root_id | 1 | RootId | A | 1 | NULL | NULL | YES | BTREE | | |
| Posts | 1 | idx_posts_hashtags_txt | 1 | Hashtags | NULL | 5 | NULL | NULL | YES | FULLTEXT | | |
| Posts | 1 | idx_posts_message_txt | 1 | Message | NULL | 5 | NULL | NULL | YES | FULLTEXT | | ngram index sample |
+-------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--------------------+
7 rows in set (0.00 sec)
コメント欄以外で区別が付かないのですが、これでngramパーサ指定のインデックスで貼り直されたはずです。確認してみます。
動作確認
こんな感じで検索結果に出るようになりました。N-gramなんで途中文字列でも当たります。
デフォルトは2-gramみたいですが、my.cnfの設定で変えられるみたいなので、そのへんはお好みで。MeCabパーサを使ってみるのもいいかもですね。
ハイライトはクライアント側?なので対応してないのですが、jump機能が使えるのであんまり気にならないかもしれません。
とりあえずやっつけ対応にしては上々じゃないでしょうか。
副作用として英単語も部分一致になったりします。
インデックス方式を変えただけなので問題は出ないだろう…と思ってはいたのですが、以下のように関係ない英語文字列がHitしたりしていたので、使っていくといろいろ怪しいかもしれません。(もともとwithはストップワードなのかな…って気もしますが)
あと上記のテーブル形式とN-gramインデックスだと、きつめのパフォーマンス低下とかあるかもしれません。
インデックス貼っただけなので何かあっても比較的すぐ元に戻せると思いますが、自己責任でよろしくお願い致します。
皆様の世知辛いMattermostライフのお役にたてば幸いです。
その他
- postgresの場合は
ts_query("english")
で実装されているので、インデックス貼り直すだけではなく手を入れないとダメっぽいのと、posgresいじるのがだんだんめんどくさくなってきて途中で投げました…- fulltext-ja + mecabでクエリ投げて動作確認まではできたんですが、RDBMS側で頑張るよりelasticsearchとかの全文検索エンジンと連携させたほうがいいかなって…
- Mattermostの実装自体はかなりわかりやすい(と思う)のでどなたか…
- fulltext-ja + mecabでクエリ投げて動作確認まではできたんですが、RDBMS側で頑張るよりelasticsearchとかの全文検索エンジンと連携させたほうがいいかなって…
- MySQL 5.7の標準組み込みパーサによる全文検索はすごく楽に使えて素晴らしかったです。
- 他にも全文検索対応してないやつでもこんな感じでやっつけ対応できそうで便利だなって思いました。
- でも、それ以上に5.7の罠が多すぎて正直辛かったです…
以上です。