管理索引

Firestore 會為每個查詢建立索引,確保查詢效能。系統會自動建立最基本查詢所需的索引。您使用及測試應用程式時,Cloud Firestore 會產生錯誤訊息,協助您建立應用程式需要的其他索引。本頁說明如何管理單一欄位複合和 [向量][vector] 索引。

透過錯誤訊息建立缺少的索引

如果您嘗試使用範圍子句進行複合查詢,但該子句未對應至現有索引,系統會傳回錯誤。錯誤訊息會提供直接連結,方便您在 Firebase 控制台中建立缺少的索引。

按照產生的連結前往 Firebase 控制台,檢查自動填入的資訊,然後按一下「建立」

如果需要向量索引,錯誤訊息會包含建立缺少的向量索引的 Google Cloud CLI 指令。執行指令來建立缺少的索引。

角色和權限

如要在 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

使用 Google Cloud Platform Console

您可以在 Google Cloud Platform 主控台中,管理單一欄位索引豁免和複合索引。

建立複合式索引

如要從 GCP 主控台手動建立新的複合式索引,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Databases」頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「索引」,然後點選「複合」分頁標籤。

  4. 按一下「建立索引」

  5. 輸入集合 ID。新增要建立索引的欄位名稱,以及每個欄位的索引模式。按一下「儲存索引」

新索引會顯示在複合式索引清單中,Firestore 也會開始建立索引。索引建立完成後,索引旁會顯示綠色勾號。

刪除複合式索引

如要刪除複合式索引,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Databases」頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「索引」,然後點選「複合」分頁標籤。

  4. 在複合索引清單中,按一下要刪除的索引的「更多」按鈕 。按一下「刪除」

  5. 按一下快訊中的「Delete Index」(刪除索引),確認要刪除這個索引。

新增單一欄位索引豁免設定

單一欄位索引豁免項目可讓您覆寫集合中特定欄位的自動索引設定。您可以透過控制台新增單一欄位豁免:

  1. 前往 Google Cloud 控制台的「Databases」頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「索引」,然後點選「單一欄位」分頁標籤。

  4. 按一下「新增豁免」

  5. 輸入「集合 ID」和「欄位路徑」

  6. 為這個欄位選取新的索引設定。啟用或停用這個欄位的自動更新升序、降序和陣列包含單一欄位索引。

  7. 按一下「儲存豁免」

新增集合層級的豁免

如要定義適用於集合 ID 底下所有欄位的單一欄位索引豁免設定,請按照下列步驟操作:

  1. 按一下「新增豁免」
  2. 輸入集合群組的「Collection ID」(集合 ID),並將「Field path」(欄位路徑) 設為 *

    選擇要豁免的欄位

  3. 選取要套用至集合群組中所有欄位的索引豁免。

  4. 按一下「儲存豁免」。

刪除單一欄位索引豁免設定

如要刪除單一欄位索引豁免設定,請執行下列步驟:

  1. 前往 Google Cloud 控制台的「Databases」頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「索引」,然後點選「單一欄位」分頁標籤。

  4. 在單一欄位索引豁免清單中,按一下要刪除豁免的「更多」按鈕 。按一下「刪除」

  5. 按一下快訊中的「刪除」,確認要刪除這項豁免。

刪除單一欄位豁免項目後,指定的欄位或子欄位會使用沿用的索引設定。文件欄位會還原為資料庫的自動索引設定。地圖中的子欄位會先繼承上層欄位的豁免設定,再繼承自動索引設定。

使用 Firebase CLI

您也可以使用 Firebase CLI 部署索引。 如要開始使用,請在專案目錄中執行 firebase init firestore。 設定期間,Firebase CLI 會產生 JSON 檔案,其中包含格式正確的預設索引。編輯檔案以新增更多索引,然後使用 firebase deploy 指令部署檔案。

如要只部署 Firestore 索引和規則,請新增 --only firestore 旗標。

如果您使用 Firebase 控制台編輯索引,請務必同時更新本機索引檔案。請參閱 JSON 索引定義參考資料

使用 Terraform

在資料庫中建立索引

Firestore 資料庫可以同時包含單一欄位和複合式索引。您可以編輯 Terraform 設定檔,為資料庫建立索引。 單一欄位和複合式索引使用不同的 Terraform 資源類型 (google_firestore_indexgoogle_firestore_field)。

支援 Firestore 原生模式和 Datastore 模式的索引。

單一欄位索引

以下範例 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。

Datastore 模式索引

您也可以使用 Terraform 建立 Datastore 模式索引。

datastore.tf

resource "google_firestore_index" "datastore-mode-index" {
  project = "project-id"
  database = "database-id"

  collection = "chatrooms"

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

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

  query_scope = "COLLECTION_GROUP"
  api_scope   = "DATASTORE_MODE_API"
}
從 google_datastore_index 遷移

google_datastore_index 資源已淘汰,將無法在 terraform-provider-google 6.0.0 以上版本中使用。

如果您先前使用 google_datastore_index 資源,可以遷移至 google_firestore_index。 如要遷移,請按照下列步驟操作:

  1. 撰寫等效的 google_firestore_index 資源。
  2. 將現有的 Datastore 模式索引匯入新資源。
  3. 移除舊 google_datastore_index 資源的參照。
  4. 從 Terraform 的狀態中移除舊的 google_datastore_index 資源。
  5. 執行 terraform apply 來套用所有變更。

詳細操作說明如下:

  1. 根據現有的 google_datastore_index 資源編寫替代 google_firestore_index。請參閱下文瞭解必要變更。
  2. 判斷索引的 Firestore 資源路徑:

    export INDEX_RESOURCE_PATH=$(echo '"projects/${google_datastore_index.datastore-index-resource-name.project}/databases/(default)/collectionGroups/${google_datastore_index.datastore-index-resource-name.kind}/indexes/${google_datastore_index.datastore-index-resource-name.index_id}"' | terraform console | tr -d '"')
    

    datastore-index-resource-name 換成現有資源的 Terraform 名稱。

  3. 將現有的 Datastore 模式索引匯入您在上方建立的 google_firestore_index 資源:

    terraform import google_firestore_index.firestore-index-resource-name $INDEX_RESOURCE_PATH
    

    firestore-index-resource-name 換成現有資源的 Terraform 名稱。

    如要進一步瞭解如何匯入 Firestore 索引資源,請參閱 google_firestore_index 參考說明文件

  4. 從 Terraform 設定檔中刪除現有的 google_datastore_index 資源。
  5. 從 Terraform 狀態中移除現有的 google_datastore_index 資源:

    terraform state rm google_datastore_index.datastore-index-resource-name
    

    如要進一步瞭解如何移除資源,請參閱「移除資源」的 Terraform 頁面。

  6. 執行 terraform plan。 驗證輸出內容,確認您並未建立或刪除任何資源。

    檢查輸出內容,確認匯入作業已順利完成。如果輸出顯示任何欄位變更,請確認這些變更是否為有意進行的操作。如果輸出內容包含類似下列的行:

    google_firestore_index.firestore-index-resource-name must be replaced
    

    然後檢查 Terraform 設定檔,看看是否有任何錯誤。

  7. 確認 Terraform 計畫輸出內容符合需求後,請執行下列指令:

    terraform apply
    

  8. 翻譯索引

    如要將 google_datastore_index 資源轉換為對應的 google_firestore_index 資源,請複製該資源並進行下列變更:

    • google_datastore_index 替換為 google_firestore_index
    • 將引數名稱 kind 替換為 collection,但引數值保持不變。
    • 將引數名稱 ancestor 替換為 query_scope。將引數值 ALL_ANCESTORS 替換為 COLLECTION_RECURSIVE,並將任何其他值替換為 COLLECTION_GROUP。如果沒有 ancestor 引數,請新增 query_scope 引數,並將值設為 COLLECTION_GROUP
    • 新增引數 api_scope,並將值設為 DATASTORE_MODE_API
    • 請將每個 properties 例項替換為對應的 fields 例項。將每個 name 例項替換為 field_path,並將每個 direction 例項替換為 order

    舉例來說,請參考這個 google_datastore_index 資源:

    datastore.tf

    resource "google_datastore_index" "legacy" {
      kind = "foo"
    
      properties {
        name = "property_a"
        direction = "ASCENDING"
      }
    
      properties {
        name = "property_b"
        direction = "ASCENDING"
      }
    }
    

    對應的 google_firestore_index 資源會是:

    resource "google_firestore_index" "new" {
      // note: defaults to the provider project
      project = project
    
      // note: defaults to the (default) database
      database = "(default)"
    
      collection = "foo"
    
      api_scope = "DATASTORE_MODE_API"
    
      // since there was no "ancestor" property set above, use COLLECTION_GROUP here
      query_scope = "COLLECTION_GROUP"
    
      fields {
        field_path = "property_a"
        order  = "ASCENDING"
      }
    
      fields {
        field_path = "property_b"
        order = "ASCENDING"
      }
    }
    

    索引建構時間

    如要建構索引,Firestore 必須先設定索引,然後使用現有資料回填索引。索引建構時間是設定時間和回填時間的總和:

    • 設定索引需要幾分鐘的時間。即使是空白資料庫,建立索引也至少需要幾分鐘。

    • 回填時間取決於新索引中現有資料的數量。與索引定義相符的欄位值越多,回填索引所需的時間就越長。

    索引建構作業屬於長時間執行的作業

    啟動索引建構作業後,Firestore 會為該作業指派不重複的名稱。作業名稱的前置字串為 projects/[PROJECT_ID]/databases/(default)/operations/,例如:

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

    不過,為 describe 指令指定作業名稱時,可以省略前置字串。

    列出所有長時間執行的作業

    如要列出長時間執行的作業,請使用 gcloud firestore operations list 指令。這個指令會列出進行中和最近完成的作業。 匯出完成後其項目會保留幾天以供存取:

    gcloud firestore operations list
    

    檢查作業狀態

    您可以列出單一作業的詳細資料,而不必列出所有長時間執行的作業:

    gcloud firestore operations describe operation-name

    估算完成時間

    作業執行時,可查看 state 欄位值,以瞭解作業的整體狀態。

    用於取得長時間執行作業狀態的要求,也會傳回 workEstimatedworkCompleted 指標。這些指標會針對文件數量傳回。workEstimated 顯示作業預計處理的文件總數。workCompleted 會顯示目前處理的文件數量。作業完成後,workCompleted 會反映出實際處理的文件總數,可能與 workEstimated 的值不同。

    workCompleted 除以 workEstimated 可得出進度的粗估值。此估計可能不準確,因為此取決於延遲的統計數據收集。

    例如,以下是索引建構作業的進度狀態:

    {
      "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 值。

    建立索引時發生錯誤

    管理複合索引和單一欄位索引豁免項目時,可能會遇到索引建構錯誤。如果 Firestore 在建立索引時遇到資料問題,索引作業可能會失敗。最常見的原因是達到索引上限。舉例來說,作業可能已達到每個文件的索引項目數量上限。

    如果索引建立失敗,控制台中會顯示錯誤訊息。確認未達到任何索引限制後,請重試索引作業。