Cloud Firestore でのインデックス管理

Cloud Firestore では、すべてのクエリにインデックスを使用することで、クエリのパフォーマンスを維持しています。最も基本的なクエリに必要なインデックスは、自動的に作成されます。Cloud Firestore を使用すると、アプリを使用してテストする際に、アプリで必要な追加のインデックスを簡単に作成できます。このページでは、単一フィールド インデックス、複合インデックス、ベクトル インデックスの管理方法について説明します。

不足しているインデックスをエラー メッセージから作成する

一方、既存のインデックスに対応しない range 句で複合クエリを実行すると、エラーが発生します。このエラー メッセージに含まれている Firebase コンソールのリンクを使用すると、不足しているインデックスを作成できます。

Firebase コンソールへのリンクをクリックして、自動的に入力された情報を確認し、[作成] をクリックします。

ベクトル インデックスが必要な場合、エラー メッセージには、不足しているベクトル インデックスを作成する Google Cloud CLI コマンドが含まれます。コマンドを実行して、不足しているインデックスを作成します。

ロールと権限

Cloud Firestore でインデックスを作成する前に、自身に次のいずれかのロールが割り当てられていることを確認してください。

  • roles/datastore.owner
  • roles/datastore.indexAdmin
  • roles/editor
  • roles/owner

カスタムロールを定義している場合、インデックスを作成するには次のすべての権限を割り当ててください。

  • datastore.indexes.create
  • datastore.indexes.delete
  • datastore.indexes.get
  • datastore.indexes.list
  • datastore.indexes.update

Firebase コンソールを使用する

Firebase コンソールから手動で新しいインデックスを作成するには:

Firebase コンソールでインデックスを作成するインターフェースの画像

  1. Firebase コンソールの [Cloud Firestore] セクションに移動します。
  2. [インデックス] タブに移動し、[インデックスを追加] をクリックします。
  3. コレクション名を入力し、インデックスを並べ替えるフィールドを設定します。
  4. [作成] をクリックします。

インデックス フィールドは、フィールドパスの制約に従う必要があります

クエリのサイズによっては、インデックスの作成に数分かかることがあります。完了すると、[複合インデックス] セクションにインデックスとその状態が表示されます。作成中の場合、Firebase コンソールにステータスバーが表示されます。

インデックスを削除する

インデックスを削除するには:

  1. Firebase コンソールの [Cloud Firestore] セクションに移動します。
  2. [インデックス] タブをクリックします。
  3. 削除するインデックスにカーソルを合わせ、コンテキスト メニューから [削除] を選択します。
  4. アラートの [削除] をクリックして、削除を確定します。

Firebase CLI を使用する

Firebase CLI を使用してインデックスをデプロイすることもできます。まず、プロジェクト ディレクトリで firebase init firestore を実行します。設定中に、デフォルトのインデックスが正しい形式で含まれている JSON ファイルが Firebase CLI により生成されます。ファイルを編集してインデックスを追加し、firebase deploy コマンドを使用してデプロイします。

Cloud Firestore のインデックスとルールのみをデプロイするには、--only firestore フラグを追加します。

Firebase コンソールでインデックスを編集する場合は、必ずローカル インデックス ファイルも更新してください。JSON インデックス定義リファレンスをご覧ください。

Terraform を使用

データベースのインデックスを作成する

Cloud Firestore データベースには、単一フィールド インデックスと複合インデックスの両方を含めることができます。Terraform 構成ファイルを編集して、データベースのインデックスを作成できます。単一フィールド インデックスと複合インデックスでは、異なる Terraform リソースタイプ(google_firestore_indexgoogle_firestore_field)が使用されます。

単一フィールド インデックス

次の Terraform 構成ファイルの例では、chatrooms コレクションの name フィールドに単一フィールド インデックスを作成します。

firestore.tf

resource "random_id" "variable"{
  byte_length = 8
}

resource "google_firestore_field" "single-index" {
  project = "project-id"
  database = "database-id"
  collection = "chatrooms_${random_id.variable.hex}"
  field = "name"

  index_config {
    indexes {
        order = "ASCENDING"
        query_scope = "COLLECTION_GROUP"
    }
    indexes {
        array_config = "CONTAINS"
    }
  }

  ttl_config {}
}
  • project-id を実際のプロジェクト ID に置き換えます。プロジェクト ID は一意である必要があります。
  • database-id をデータベース ID に置き換えます。

複合インデックス

次の Terraform 構成ファイルの例では、chatrooms コレクションの name フィールドと description フィールドの組み合わせに複合インデックスを作成します。

firestore.tf

resource "google_firestore_index" "composite-index" {
  project = "project-id"
  database = "database-id"

  collection = "chatrooms"

  fields {
    field_path = "name"
    order      = "ASCENDING"
  }

  fields {
    field_path = "description"
    order      = "DESCENDING"
  }

}
  • project-id を実際のプロジェクト ID に置き換えます。プロジェクト ID は一意である必要があります。
  • database-id をデータベース ID に置き換えます。

ベクトル インデックス

次の Terraform 構成ファイルの例では、chatrooms コレクションの embedding フィールドにベクトル インデックスを作成します。

firestore.tf

resource "google_firestore_index" "vector-index" {
  project = "project-id"
  database = "database-id"
  collection = "chatrooms"

  fields {
    field_path = "__name__"
    order = "ASCENDING"
  }

  fields {
    field_path = "embedding"
    vector_config {
      dimension = 128
      flat {}
    }
  }
}
  • project-id を実際のプロジェクト ID に置き換えます。プロジェクト ID は一意である必要があります。
  • database-id をデータベース ID に置き換えます。

インデックスの構築時間

インデックスを構築するには、Cloud Firestore によりインデックスがセットアップされ、既存データにインデックスがバックフィルされる必要があります。インデックスの構築時間は、設定時間とバックフィル時間の合計です。

  • インデックスの設定には数分かかります。インデックスの最小構築時間は、空のデータベースであっても数分です。

  • バックフィル時間は、新しいインデックスに既存のデータがどの程度存在するかによって異なります。インデックス定義に一致するフィールド値が多いほど、インデックスのバックフィルにかかる時間が長くなります。

インデックスの構築は長時間実行オペレーションになります。

インデックスの構築を開始すると、Cloud Firestore によりオペレーションに一意の名前が割り当てられます。次のように、オペレーション名の先頭には projects/[PROJECT_ID]/databases/(default)/operations/ という文字列が付きます。

projects/project-id/databases/(default)/operations/ASA1MTAwNDQxNAgadGx1YWZlZAcSeWx0aGdpbi1zYm9qLW5pbWRhEgopEg

ただし、describe コマンドのオペレーション名を指定するときは、接頭辞を省略できます。

すべての長時間実行オペレーションの一覧表示

長時間実行オペレーションを一覧表示するには、gcloud firestore operations list コマンドを使用します。このコマンドは、実行中のオペレーションと最近完了したオペレーションを一覧表示します。オペレーションは、完了後数日間一覧表示されます。

gcloud firestore operations list

オペレーションのステータスを確認する

すべての長時間実行オペレーションを一覧表示する代わりに、1 つのオペレーションの詳細を一覧表示できます。

gcloud firestore operations describe operation-name

完了時間の見積もり

オペレーションを実行すると、state フィールドの値で、オペレーション全体のステータスが確認できます。

長時間実行オペレーションのステータスをリクエストすると、workEstimatedworkCompleted の指標も合わせて返されます。これらの指標はドキュメント数で返されます。workEstimated には、オペレーションで処理される推定の合計ドキュメント数が表示されます。workCompleted には、これまでに処理されたドキュメント数が表示されます。オペレーションが完了すると、workCompleted には実際に処理されたドキュメントの合計数が反映されます。これは workEstimated の値とは異なる場合があります。

進行した割合を大まかに得るには、workCompletedworkEstimated で割ります。この割合は、最新の統計情報コレクションとの間に遅延があるために正確ではない可能性があります。

例として、インデックス構築の進行状況を次に示します。

{
  "operations": [
    {
      "name": "projects/project-id/operations/AyAyMDBiM2U5NTgwZDAtZGIyYi0zYjc0LTIzYWEtZjg1ZGdWFmZWQHEjF0c2Flc3UtcmV4ZWRuaS1uaW1kYRUKSBI",
      "metadata": {
        "@type": "type.googleapis.com/google.firestore.admin.v1.IndexOperationMetadata",
        "common": {
          "operationType": "CREATE_INDEX",
          "startTime": "2020-06-23T16:52:25.697539Z",
          "state": "PROCESSING"
        },
        "progressDocuments": {
          "workCompleted": "219327",
          "workEstimated": "2198182"
        }
       },
    },
    ...

オペレーションが完了すると、オペレーションの説明に、"done": true が含まれます。オペレーションの結果をみるには、state フィールドの値を確認します。done フィールドがレスポンスに設定されていない場合、値は false になります。進行中のオペレーションに関しては、done の値の有無は参考になりません。

インデックス構築エラー

複合インデックスと単一フィールド インデックスの例外を管理するときに、インデックス構築エラーが発生することがあります。Cloud Firestore がインデックスを作成しているデータで問題を検出すると、インデックス作成オペレーションに失敗する可能性があります。多くの場合、インデックスの上限に達すると、この問題が発生します。たとえば、オペレーションでドキュメントあたりの最大インデックス エントリ数に達した可能性があります。

インデックスの作成に失敗すると、コンソールにエラー メッセージが表示されます。インデックスの上限に達していないことを確認した後、インデックス オペレーションを再試行します。