先にまとめ
- たぶん先にウェブコンソールで編集 → 結果を JSON へ保存、という流れ
firebase firestore:indexes
で「現在設定されているインデックス」をJSONで得られる- なので、書式は不明だけど気にする必要なさそう
- エラーメッセージにインデックス作成 URL が含まれる(のでそれを使う)
ここまでのあらすじ
一覧を新しいもの順にしようと orderBy()
追加したらエラーになった。
const collRef = firebase.firestore().collection(collectionName) .where('userId', '==', userId) .orderBy('updatedAt', 'desc');
FirebaseError: The query requires an index. You can create it here: https://console.firebase.google.com/project/your-project/database/firestore/indexes?create_composite=…
このクエリーにはインデックスが必要だよ、この URL から作れるよ。とのこと。
インデックスを作成する
firestore.indexes.json
が気になるところなんだけど、後回し。
エラーメッセージに含まれる URL を開くと Firestore の Indexes のページが出てきて、「インデックス作るよ!」というダイアログが表示される。
素直に “Create index” ボタンを押せばすぐ作ってくれる。
いや、すぐは作ってくれない
すぐ作り始めてはくれるんだけど、なかなか時間がかかる様子。
更新が必要なデータ量によっては、インデックスの作成に数分かかる場合があります。
手元の 10 件ない程度の環境で、完了まで 30 秒くらいにかかった。
インデックスを firestore.indexes.json
で管理する
後から環境を再現できるようリポジトリーに設定を持っておきたい。わかる。
firebase init
で firestore.indexes.json
というファイルを作ってくれるんだけど、どうやらこのJSONファイルをいじるのではなく、先にコンソールで作業してから記録するというのが良さそう。
つまりこんな流れ。
- ウェブのコンソールで作業(前節でやった)
firebase
で定義のスナップショットをfirestore.indexes.json
へ保存- 必要に応じて
firebase
からデプロイして環境を再現
スナップショットを保存
スナップショットという表現で良いのかわかんないけども。
firebase
コマンドで現在設定されているものをJSONで得られる。標準出力に出てくるので、>
を使ってJSONファイルへ上書き出力してやる。
$ firebase firestore:indexes > firestore.indexes.json
結果、例えばこんな感じであるらしい。
{ "indexes": [ { "collectionGroup": "rooms", "queryScope": "COLLECTION", "fields": [ { "fieldPath": "userId", "order": "ASCENDING" }, { "fieldPath": "updatedAt", "order": "DESCENDING" } ] } ], "fieldOverrides": [] }
デプロイして環境再現
本番環境を更新するとか開発環境を作り直すとかは、JSON ファイルを用意したあとは普通にデプロイするだけ。インデックスだけの場合は --only firestore:indexes
で。
$ firebase deploy --only firestore:indexes
最初間違えて単数 firestore:index
とやってしまい、でもエラーにならないので気づくのに時間がかかった……。
なお JSON へ追加してデプロイすると作成してくれるけど、JSON で削除してデプロイしても実際に削除してくれない。 (追記 2021-02-13)確認して削除してくれるようになっていた。
i deploying firestore
i firestore: reading indexes from firestore.indexes.json...
i firestore: The following indexes are defined in your project but are not present in your firestore indexes file:
(rooms) -- (userId,ASCENDING) (updatedAt,DESCENDING)
? Would you like to delete these indexes? Selecting no will continue the rest of the deployment.
Yes
i firestore: Deleting 1 indexes...
✔ firestore: deployed indexes in firestore.indexes.json successfully
べんり!(追記おわり)
コマンド詳細
$ firebase firestore:indexes --help Usage: firestore:indexes [options] List indexes in your project's Cloud Firestore database. Options: --pretty Pretty print. When not specified the indexes are printed in the JSON specification format. -h, --help output usage information
CI でデプロイするとしばらくエラーに
Firestoreのindexes作成にちょっと時間かかるから、まとめてdeployするとその完了前にhostingの方が完了してしまい、数分間エラーになってしまう……。
— 高梨ギンペイ (@ginpei_jp) June 2, 2019
CI から firebase deploy
するプロジェクトで試したところ、Firestore の更新も Hosting へのアップロードも同時に行われるため、Firestore のこのインデックス作成完了までの間はエラーになってしまった。なんか対応のしようがあるんだろうか? いったん firebase deploy --only firestore:indexes
して、準備完了をどうにかして検知して、それから Hosting を更新するなんてことができる?
削除して再作成
削除はコンソールで Firestore → Indexes の一覧右側 “…” から。すぐ終わる。
終わるが、そのあとすぐに作り直そうとするとエラーになった。
$ firebase deploy --only firestore:indexes === Deploying to 'my-project'... i deploying firestore i firestore: reading indexes from firestore.indexes.json... Error: HTTP Error: 409, index already exists
たぶんサーバー側の中のどこかでキャッシュみたいなものが残ってるんではなかろうか。知らんけど。
3 分程度間をおいて再実行したら成功した。作成と同様、量によって時間が伸びると思う。
セキュリティルールは先に JSON を書く
じゃあインデックスだけじゃなくてセキュリティルールも先にコンソールでやるのか、と思ったけどどうもそうでもないらしい。
firebase --help
で出てくるコマンド一覧には、Firestore 関連のものはこの indexes
と delete
のふたつだけ。やっぱりコンソールで試して → JSON コピペして保存して → デプロイ、という流れか。
おしまい
参考
- Cloud Firestore でのインデックス管理 | Firebase
- firebase – What is the JSON format for a firestore composite index including an array? – Stack Overflow
更新履歴
- 2019-06-01 初版
- 2019-06-10 「CI でデプロイするとしばらくエラーに」追加