noellabo's tech blog

@noellaboの技術ブログ

Elasticsearch 7.0 をMastodonでムリヤリ使う

別に、どうしても elasticsearch 7.0 を使いたい理由なんて無いんですが、まぁ、面白そうじゃないですかw

おさらい

  • Mastodonは、chewyというgemを使ってElasticsearchに対応しています
  • chewyは、elasticsearch-rubyというgemを使っています
  • elasticsearch-rubyの最新版はv7.0.0で、着々とv7.0への対応が進められています

互換性がない部分

型情報が無くなった

Mastodon v2.8.0は、elasticsearch用に以下のようなマッピングをstatusという型で定義しているのですが、

"mappings" : {
    "status": {
        "date_detection": false,
        "properties": {
            "account_id": {
                "type": "long"
            },
            "id": {
                "type": "long"
            },
            "text": {
                "type": "text",
                "fields": {
                    "stemmed": {
                        "analyzer": "content",
                        "type": "text"
                    }
                }
            },
            "searchable_by": {
                "type": "long"
            }
        }
    }
}

elasticsearchは、型を無くす方向で順次切り捨てに入っており、型をつけて投げるとエラーになります。

このように、型を削除して投げればOKです。

"mappings" : {
    "date_detection": false,
    "properties": {
        "account_id": {
            "type": "long"
        },
        "id": {
            "type": "long"
        },
        "text": {
            "type": "text",
            "fields": {
                "stemmed": {
                    "analyzer": "content",
                    "type": "text"
                }
            }
        },
        "searchable_by": {
            "type": "long"
        }
    }
}

ヒットした件数の表現が変わった

6までは数値で件数が返されてきたのですが、

"total": 1,

7.0では数値と数値の意味(ぴったりその数eqなのか、それ以上gteという参考値なのか)を返してきます。

"total" : {
    "value" : 1,
    "relation" : "eq"
},

どうするか

最初に触れたように、Mastodon自体が直接elasticsearchを呼んでいるワケではないので、Mastodonのソースコードをいじっても対応できません。

chewyがelasticsearch 7.0に対応するのを待って、Mastodonでその対応版を使う、というのが正解なんですが、chewyって最終更新が半年前ぐらい前で、あまりアクティブじゃないので、たぶんすぐには対応してくれない。しばらくかかりそうです。

幸い、とりあえず上記の非互換性については、オプションで以前と同じ挙動に変更できるようにしてくれています。まぁ一応対応残しておくけど、8.0になったらそれも切り捨てるから、今のうちになんとかしろ、という感じです。

しょうがないので、chewyをフォークして、elasticsearch-rubyのv7.0.0を参照し、必要なところに互換性設定のオプション指定した、やっつけブランチを作ることにします。Mastodonの方で、そいつをGemfileに指定してやればOKという寸法です。

オプションですが、型についてはinclude_type_name=trueって付ければ、型がついていても受理するよ、ということです。件数はrest_total_hits_as_int=trueって指定すれば、これまでと同じように数値で返すよ、ということです。

というわけで、ウチでフォークして作ったやっつけコミットはこちら。これをMastodonで使ってやればOKです。 ES6 client compatibility workaround for ES7 -- noellabo/chewy

elasticsearch 7.0、パフォーマンス改善したり、メモリ使い切らないように制御したり、なにやら地味に良くなっているので、早く周辺環境含めて対応できるといいですね。

Mastodonの対応

ある程度詳しい人しかやらないと思うので、例によって雑に説明します。

まず、手元の作業用リポジトリで適当にブランチ切って下さい。

git checkout -b feature-compatibility-workaround-for-es7

Gemfilechewyのところを書き換えます。

gem 'chewy', git: 'https://github.com/noellabo/chewy.git', branch: 'es6-client-compatibility-workaround-for-es7'

で、bundle installして、Gemfile.lockを更新します。

git add .
git commit -m "Compatibility workaround for ES7"

commitして、このブランチで動作確認してから、本番適用してください。

日本語ダメダメなので、sudachiとか使った方がいいよ

Mastodonの標準の状態だと日本語の処理がダメダメでちゃんと出て欲しい言葉が検索できないので、sudachiなどを使うように設定した方が良いです。これについては記事を書いてあるので、そちらを参考にしてください。sudachi、もう7.0に対応してるの、ホントありがたい……。

ElasticsearchをMastodonとは別のサーバに設置する

別の方法(プロキシを使う)

Balさんがスマートな解法を編み出していたので、紹介させていただきます。

ElasticsearchはREST APIなので、間にプロキシを挟んで、そこで上述した互換オプションを追加してしまうという方法です。オプションの指定はURLに追加するので、rewriteで対応できるというわけです。賢すぎる。 https://ifrit.gaia.ff14-mstdn.xyz/@Bal_Ballard/101976201167730363