iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【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 のセットアップは完了している前提ですので、まだ完了していない場合は以前に僕が書いた記事を参照していただければいくらか参考になるかと思います。

yamato8010.hatenablog.com

yamato8010.hatenablog.com

それでは早速、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.uideventDate のフィールドを使用したかったので、それぞれ定義をしています。order は、どの並び順でインデックスを保持するのかを決定するために指定する必要があります。今回は、ASCENDING として保持しました。なお、guide.uid によって DESCENDING の順で結果を取得したい場合や、eventDate によって DESCENDING の順で結果したい場合などは、別途 field を追加して設定するか、元の fieldorder を書き換える必要があります。Firestore で不等式句を使用してクエリを行う場合は、デフォルトで ASCENDING によって結果が取得されるので、DESCENDING のみでインデックスを作成して、うっかりそのままリクエストしてしまうとエラーが発生してしまうので注意が必要です。

最後に、作成したインデックスをデプロイしたら完了です🎉

$ firebase deploy --only firestore:indexes

という感じで本日も以上になります👷‍♀️ それではまた明日。

参考

firebase.google.com

firebase.google.com

firebase.google.com

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com