kurage.cc マストドンに日本語対応の全文検索を導入 kurage.cc

ぜま✅クラゲ丼鯖缶 2018年2月19日(月)
こんにちは。
従来から検索が弱いと言われていたマストドンですが、2月10日のアップデート(#6423)に初の全文検索機能が盛り込まれました。私が管理しているクラゲ丼にフリーワード検索はどうしても欲しいと以前から思っていたこともあり、早速マージして使ってみました。いろいろとつまづきポイントがあってなかなかすんなりとはいかず、試行錯誤することになりましたが、とりあえず約1週間でここまでたどり着いたというあたりでいったん記事にまとめてみたいと思います。
なお、たるんたるんのMayaさんから今回の件では多数の助言をいただきました。ありがとうございました。
(環境:さくらのクラウド CentOS 非Docker)


1 まずは#6423をマージ

 全文検索機能はv2.2.0より新しいコミットなのでまだ今のところ正式リリースではありません。まずはmaster追従するなりして#6423をマージします。以下は一例ですね (なお#6464に問題があります。後述)
# su - mastodon $ cd /home/mastodon/live $ git pull --no-edit $ bundle install --deployment --without development test $ yarn install $ RAILS_ENV=production bundle exec rake db:migrate $ RAILS_ENV=production bundle exec rake assets:precompile $ exit # systemctl restart mastodon*

2 .env.productionの編集

 .env.production.sample の12~15行目あたりに書かれている項目を .env.production に追記することが必要です。sampleではコメントアウトされていますが、有効化したいので行頭「#」を取り除いたものを追記します。
$ vi /home/mastodon/live/.env.production # Optional ElasticSearch configuration ES_ENABLED=true ES_HOST=localhost ES_PORT=9200

3 Java 8 (JDK-1.8.0) のインストール

 今回の全文検索は Elasticsearch というのを使っていて、これを動作させるために Java 8 が必要なんだそうです。古かったり入ってなかった場合はインストールします。
# yum install java-1.8.0-openjdk-devel.x86_64
 バージョン確認
$ java -version openjdk version "1.8.0_161" OpenJDK Runtime Environment (build 1.8.0_161-b14) OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)

4 Elasticsearch のインストール

 (参考: 公式ドキュメント Install Elasticsearch with RPM)  まず Elasticsearch PGP Key のインポートをします
# rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
 次にリポジトリの設定をします。まっさらなエディタが開くので下の8行を貼り付けて保存します。
# vi /etc/yum.repos.d/elasticstack.repo [elasticsearch-6.x] name=Elasticsearch repository for 6.x packages baseurl=https://artifacts.elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md
 Elasticsearch をインストールします。
# yum install elasticsearch
 エディタを開いて設定します。下の -Xms512m と- Xmx512m はメモリ割り当てです。Elasticsearch は非常にメモリ大食いでサーバーが重くなってしまうのですが、ここの数値を下げるとある程度改善することができるので調整してみて下さい。クラゲ丼は -Xms256m と- Xmx256m に落として今のところ問題なく使えています。
# vi /etc/elasticsearch/elasticsearch.yml network.host: localhost # vi /etc/elasticsearch/jvm.options -Xms512m -Xmx512m
 Elasticsearch を起動します。自動起動の設定も行います。
# systemctl start elasticsearch # systemctl enable elasticsearch
 動作確認。 Activeであることを確認します。
# systemctl status elasticsearch
これも動作確認。なんかこんなのが出ればたぶん正常です。
# curl localhost:9200 { "name" : "T_9NHuw", "cluster_name" : "elasticsearch", "cluster_uuid" : "bUB5BFzFRfmQLLlKN5YmaA", "version" : { "number" : "6.2.1", "build_hash" : "7299dc3", ... ...
 ググるとこのあとに Kibana などのインストール手順が書いてあったりしますが、ここでは必要ありません。  まだ日本語対応してませんがとりあえずこれで検索はできるはずです。ただしまず過去のトゥートをスキャンしてインデックスを更新するために #6423 に書いてあるように chewy:deploy というrakeタスクを走らせる必要があります。このタスクは日々実行する必要はなさそうですがべらぼうに時間がかかるので(クラゲ丼の場合で約2時間)あまりむやみにやると後悔します。この段階で検索のテストをしてみたい場合は走らせてみてください。すぐ次に進む場合は飛ばして大丈夫です。  なお、再起動をかける場合は Elasticsearch だけ再起動すると整合性がおかしくなって500エラーが出たりすることがあったので、マストドンも落としたほうが無難なようです。500エラーは再度 chewy:deploy すればたぶん直ります。
$ RAILS_ENV=production bundle exec rake chewy:deploy $ exit # systemctl restart mastodon* elasticsearch

5 謎の #6464 (解決したのでここは飛ばしてください)

 検索のテストをしているうち、どうも #6464 というコミットはマージしないほうが良さそうだということになりました。理由は、こいつをマージするとsidekiqの「待機状態」のところにキューがやたらと積まれてしまう気持ちの悪いことが起こり、しかも新しいトゥートが検索対象に入らないのです。(Revertすると直る)  オイゲンさんが入れたんだから何か意味のあるコミットなんだとは思いますが(オイゲンさんの意図がよくわかっていません)弊害が大きいので、Revertするか、このコミットの変更点は1行だけなのでマージ後に行頭「#」をつけてコメントアウトします。  【2/21追記】 上記の不具合について Mayaさんissue(#6509) を上げてくださり、これを受けてオイゲンさんから修正プルリク(#6513)が出てmasterにマージされたので、この問題は解決した模様です。

6 表示される検索結果の件数を増やす

 今回のアップデートではデフォルトでは検索結果が5件しか表示されません。これでは不便なので上限を書き換えます。ただしサーバーの負荷が増すと思われるので注意が必要かもしれません。
$ vi /home/mastodon/live/app/controllers/api/v1/search_controller.rb RESULTS_LIMIT = 100

7 検索対象のアカウントを増やす

 今回のアップデートではデフォルトでは検索する本人のトゥート(本人がお気に入り・ブーストしたトゥートを含む)しか表示されません。鯖缶さんのアカウントなど全員に表示されてもかまわないものがあれば検索結果に含めた方がよいと思うので、制限を書き換えます。(下の例は追加する鯖缶のIDが「1」である場合です)
$ vi /home/mastodon/live/app/services/search_service.rb def perform_statuses_search! statuses = StatusesIndex.filter(terms: { searchable_by: [account.id, 1] })

8 日本語対応させる(kuromojiのインストール)

 マストドンのアップデートでは英語以外の各国語への対応は現時点で考慮されていませんが、Elasticsearchには公式で kuromoji という日本語用の形態素解析プラグインがあります。これを入れておかないと(日本語は英語のように単語がスペースで区切られていないため)単語を認識できず、1文字ずつの検索になってしまいます(例えば「おでん」で検索しても「お」「で」「ん」の3文字を含むトゥートがすべてヒットしてしまう。「おでん」と「んでお」が同じ検索結果になる)。入れることで検索結果がだいぶ良くなるので是非ともkuromojiを入れましょう。
# /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji
 インストールしたら app/chewy/statuses_index.rb の3~32行目までをがばっと書き換えます。
$ vi /home/mastodon/live/app/chewy/statuses_index.rb 削除 class StatusesIndex < Chewy::Index settings index: { refresh_interval: '15m' }, analysis: { filter: { english_stop: { type: 'stop', stopwords: '_english_', }, english_stemmer: { type: 'stemmer', language: 'english', }, english_possessive_stemmer: { type: 'stemmer', language: 'possessive_english', }, }, analyzer: { content: { tokenizer: 'uax_url_email', filter: %w( english_possessive_stemmer lowercase asciifolding cjk_width english_stop english_stemmer ), }, }, } 追加 class StatusesIndex < Chewy::Index settings index: { refresh_interval: '15m' }, analysis: { tokenizer: { kuromoji_user_dict: { type: 'kuromoji_tokenizer', user_dictionary: 'userdic.txt', }, }, analyzer: { content: { type: 'custom', tokenizer: 'kuromoji_user_dict', filter: %w( kuromoji_baseform kuromoji_stemmer cjk_width lowercase ), }, }, }
 最後にユーザ辞書ファイルを作ります。(これは必須ではありませんが)単語は使用頻度の高いもの、ひらがなの多いものを入れておくと検索が改善します。ユーザ辞書を作らない場合は上の「user_dictionary:」の行を消しておいたほうがいいかも。
# vi /etc/elasticsearch/userdic.txt けもフレ,けもフレ,ケモフレ,名詞 ぬるかる,ぬるかる,ヌルカル,名詞 ... ...
これでたぶん終わりです。いろいろ編集したので assets:precompile、chewy:deploy して再起動します。
$ git add -A $ git commit -m "Apply Japanese(kuromoji) analyzer" $ RAILS_ENV=production bundle exec rake assets:precompile $ RAILS_ENV=production bundle exec rake chewy:deploy $ exit # systemctl restart mastodon* elasticsearch
お疲れさまでした。

続報

 【2/21追記】 これを書いていた時点で Elasticsearch の最新版は 6.2.1 でしたが、ちょうど 6.2.2 がリリースされたので上げてみたところ、 Elasticsearch が起動しなくなるトラブルが発生しました。これはプラグインの kuromoji が自動的には上がらないためで、Elasticsearch をアップデートした場合には kuromojiの再インストールが必要になるようです。
# yum update elasticsearch.noarch # /usr/share/elasticsearch/bin/elasticsearch-plugin remove analysis-kuromoji # /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji

過去の記事:マストドンのwebUIを透過色にして壁紙を適用する方法 次の記事:マストドンの全文検索に形態素解析器 Sudachi を導入 クラゲ丼 (kurage.cc)