Docker Compose版Misskeyにノート検索 (Meilisearch) を導入する

自宅Misskeyサーバ https://mi.arkw.work/ にMeilisearchを導入し、ノート検索機能を有効化した記録です。  
作業自体は簡単ですが、文献が少なく (なんと! Misskey Hubにまだ書かれていない) 割と苦労しました。

# 環境

- Rocky Linux 8.6
- Docker 24.0.2 + Docker Compose 2.2.0
- Misskey 13.14.2

# 導入手順

## コンフィグの編集

まず `docker-compose.yml` を開き、`meilisearch` セクションのコメントアウトを外します。

```yml
meilisearch:
  restart: always
  image: getmeili/meilisearch:v1.1.1
  environment:
    - MEILI_NO_ANALYTICS=true
    - MEILI_ENV=production
  env_file:
    - .config/meilisearch.env
  networks:
    - internal_network
  volumes:
    - ./meili_data:/meili_data
```

記載されている通り `.config/meilisearch.env` を必要としますが、初期状態では存在しません。  
Docker ComposeやMisskeyのコンフィグと違いテンプレートは用意されていないため、1から作成します。  

```plaintext
MEILI_MASTER_KEY="ここにマスターキーを入力"
```

中身はこれだけ。16バイト以上の文字列 (UUIDとか) を適当に生成し、マスターキーとします。

次に `.config/default.yml` を開き、Docker Compose 設定ファイルと同様に `meilisearch` セクションのコメントアウトを外します。  
`ssl` の初期値は `true` ですが、当方の環境では動作しなかったため無効化しています。

```yml
#   ┌───────────────────────────┐
#───┘ MeiliSearch configuration └─────────────────────────────

meilisearch:
  host: meilisearch
  port: 7700
  apiKey: 'ここにマスターキーを入力'
  ssl: false
  index: 'ここにインデックス名を入力'
```

Misskey 13.12.2以降のバージョンでは、Meilisearchのインデックス名が必須となっています。アルファベット、ハイフン、アンダーバーのみ使用でき、Misskey Hubではサーバのホスト名が推奨されています。(例: https://misskey.io なら `misskey-io`)

コンフィグの編集は以上です。念のためDockerコンテナをリビルドし、再起動します。

```sh
$ sudo docker compose build
$ sudo docker compose stop && sudo docker compose up -d
```

## フロントエンド側の設定

ウェブブラウザでMisskeyを開き、`コントロールパネル` → `ロール` → `ベースロール` の `ノート検索の利用可否` を `はい` に変更します。

![Screenshot 2023-09-11 at 10-58-18 mi.arkw.work.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114838/48388642-f8e0-4b4f-a782-c9aaad4b9ae5.png)

これでノート検索が使えるようになります。

![Screenshot 2023-09-11 at 10-59-29 mi.arkw.work.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114838/cbb82e05-c918-02a0-d541-3db89a80e50d.png)

## 過去に投稿したノートも検索できるようにする

**【おことわり】データベーススキーマ変更に伴い、Misskey 2023.9以降では以下の方法が使えません。対処法は後日追記予定です。**

Meilisearch導入前に投稿したノートを検索するには、別途インデックスを張る必要があります。

まずPostgresQLのDockerコンテナに入り、ノートの一覧を出力します。  
`psql` コマンドの `-U` オプションには `.config/docker.env` の `POSTGRES_USER`、`-d` オプションには `POSTGRES_DB` をそれぞれ指定してください。

```bash
$ sudo docker compose exec -it db /bin/bash
# psql -U misskey -d misskey -c "SELECT json_agg(row_to_json(t)) ::text  FROM (SELECT id, \"createdAt\", \"userId\", \"userHost\", \"channelId\",cw,text FROM note WHERE visibility IN ('home', 'public')LIMIT 10000) t" > /var/lib/postgresql/data/notes_tmp
# exit
```

Meilisearchへインポートするため、出力したデータをJSON形式に変換します。

```bash
$ sudo yum install jq
$ sudo sed -i '1d;2d;x;$d;' ./db/notes_tmp
$ sudo jq 'map(.createdAt |= (strptime("%Y-%m-%dT%H:%M:%S%Z") | mktime | . * 1000 + (. / 1000000 | floor)))' ./db/notes_tmp > ./notes.json
$ sudo mv notes.json meili_data
```

MeilisearchのDockerコンテナに入り、上記で作成したJSONファイルを `curl` でPOSTすれば終了です。  
Misskeyを再起動する必要はありません。

```bash
$ sudo docker compose exec -it meilisearch /bin/ash
# curl -X POST 'http://localhost:7700/indexes/ここにインデックス名を入力---notes/documents' --data @/meili_data/notes.json -H 'Content-Type: application/json' -H "Authorization: Bearer ここにマスターキーを入力"
# exit
```

これで、過去のノートも検索できるようになりました。

![Screenshot 2023-09-13 at 17-34-12 mi.arkw.work.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114838/dfdeab89-19e4-879d-f204-1b2893cd4e64.png)

# 参考文献

https://github.com/misskey-dev/misskey/issues/10788

https://misskey.tsub.me/notes/9emmeb7yhn

https://misskey-hub.net/docs/releases.html

https://misskey-hub.net/docs/install/docker.html

https://nanasi-apps.xyz/misskey-meilisearch