【Firestore】複合インデックスを作ってみる
みなさん、Firestore
は使っていますか?僕は、個人で開発中のアプリでがっつり利用させてもらっている(Firebase信者)ので日々 Firestore
と格闘しています🤺
今回はそんな Firestore
で複合インデックスを作成する機会があったのでメモしておきます。
複合インデックスってなんぞや?
複合インデックス
とは、複数のフィールドの条件に応じて並べ替えられ、マッピングされたもののことを指します。Firestore
では、単一のフィールドに対するインデックスである 単一フィールドインデックス
は Firestore
の自動インデックスという機能によって保持されます。ちなみに、自動的に作成されるインデックスはフィールドの種類によって異なり、具体的には下記のようなものが作成されます。
配列でもなくマップでもないフィールドに対しては、コレクションのスコープを使用する 2 つの単一フィールド インデックス(1 つは昇順モード、1 つは降順モード)が定義されます。
マップ フィールドに対しては、マップ内の配列でもなくマップでもないサブフィールドごとに、コレクションのスコープを使用する 1 つの昇順インデックスと 1 つの降順インデックスが作成されます。
ドキュメント内の配列フィールドに対しては、コレクションのスコープ配列の内容インデックスが作成、維持されます。
参照: https://firebase.google.com/docs/firestore/query-data/index-overview?hl=ja#automatic_indexing
Firestore
では、フィールドの増加により、可能となるフィールドの組み合わせが多くなってしまうため自動的に 複合インデックス
が作成される事はなく、今回のように開発者自身がインデックスを設定する必要があります。
実際に作ってみる
複合インデックスを作成する手順は主に二つあり、一つ目が Firebase Console
上で作成する方法で、もう一つが Firebase CLI
を使って作成する方法です。基本的にプロジェクトが管理しているインデックスを git
などでバージョン管理などする必要がない場合は、前者の方法が最も簡単に行うことができます。また、複合クエリ
の設定が必要なリクエストを Firestore
に投げた場合(複合インデックスの設定が未完了)にはコンソールに
複合インデックス` を作成するためのリンクが表示されるので、それを元に作成するとシンプルに必要なクエリだけを追加することができます。
今回は、git
などでインデックスをバージョン管理したいので、後者の方法で 複合インデックス
を作成していきたいと思います。
ちなみに、Firebase CLI
のセットアップは完了している前提ですので、まだ完了していない場合は以前に僕が書いた記事を参照していただければいくらか参考になるかと思います。
それでは早速、Firebase
プロジェクトのルートにある firestore.indexes.json
を開いて編集していきます。今回の例では、guide
という Map
値に含まれる uid
という String
値 と eventDate
という Timestamp
値 による 複合インデックス
を作成しています。
{ "indexes": [ { "collectionGroup": "requests", "queryScope": "COLLECTION", "fields": [ { "fieldPath": "guide.uid", "order": "ASCENDING" }, { "fieldPath": "eventDate", "order": "ASCENDING" } ] } ], "fieldOverrides": [] }
まずは、collectionGroup
で、複合インデックスを作成する対象となる Collection
を指定します。次に queryScope
で、単一のコレクションとして作成するか、もしくは CollectionGroup
として作成するかを選択しています。今回は単一のコレクションとして作成したかったので、COLLECTION
としています。最後に、条件となるフィールを fields
配列に設定していきます。今回は前述の通り guide.uid
と eventDate
のフィールドを使用したかったので、それぞれ定義をしています。order
は、どの並び順でインデックスを保持するのかを決定するために指定する必要があります。今回は、ASCENDING
として保持しました。なお、guide.uid
によって DESCENDING
の順で結果を取得したい場合や、eventDate
によって DESCENDING
の順で結果したい場合などは、別途 field
を追加して設定するか、元の field
の order
を書き換える必要があります。Firestore
で不等式句を使用してクエリを行う場合は、デフォルトで ASCENDING
によって結果が取得されるので、DESCENDING
のみでインデックスを作成して、うっかりそのままリクエストしてしまうとエラーが発生してしまうので注意が必要です。
最後に、作成したインデックスをデプロイしたら完了です🎉
$ firebase deploy --only firestore:indexes
という感じで本日も以上になります👷♀️ それではまた明日。