Управление индексами в Cloud Firestore

Cloud Firestore обеспечивает высокую производительность запросов, требуя индекс для каждого запроса. Индексы, необходимые для самых простых запросов, создаются автоматически. При использовании и тестировании приложения Cloud Firestore генерирует сообщения об ошибках, которые помогают создавать дополнительные индексы, необходимые для приложения. На этой странице описано, как управлять автоматическими, созданными вручную и векторными индексами.

Как создать отсутствующий индекс с помощью сообщения об ошибке

Если вы попытаетесь выполнить составной запрос с предложением диапазона, которое не сопоставляется с существующим индексом, вы получите сообщение об ошибке. В сообщении об ошибке будет прямая ссылка на создание недостающего индекса в консоли 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, выполните следующие действия:

Изображение интерфейса индексирования Firestore в консоли Firebase

  1. В консоли Firebase выберите Databases & Storage (Базы данных и хранилище) > Firestore.
  2. На вкладке Индексы нажмите Добавить индекс.
  3. Введите название коллекции и укажите поля, по которым нужно упорядочить индекс.
  4. Нажмите Создать.

Поля индекса должны соответствовать ограничениям на пути к полям.

Создание индексов может занять несколько минут в зависимости от размера запроса. После создания индексов вы можете посмотреть их и их статус в разделе Составные индексы. Если они ещё создаются, в консоли Firebase будет показана строка состояния.

Удалить индексы

Чтобы удалить индекс, выполните следующие действия:

  1. В консоли Firebase выберите Databases & Storage (Базы данных и хранилище) > Firestore.
  2. На вкладке Индексы наведите указатель мыши на индекс, который нужно удалить, и выберите Удалить в контекстном меню.
  3. Подтвердите действие, нажав Удалить в окне оповещения.

Как использовать интерфейс командной строки Firebase

Вы также можете развернуть индексы с помощью интерфейса командной строки Firebase. Чтобы начать, запустите firebase init firestore в каталоге проекта. Во время настройки интерфейс командной строки Firebase генерирует JSON-файл с индексами по умолчанию в правильном формате. Добавьте в файл дополнительные индексы и разверните его с помощью команды firebase deploy.

Чтобы развернуть только индексы и правила Cloud Firestore, добавьте флаг --only firestore.

Если вы вносите изменения в индексы с помощью консоли Firebase, не забудьте обновить локальный файл индексов. Подробную информацию можно найти в справочнике по определению индексов JSON.

Использовать Terraform

Создание индексов в базе данных

Базы данных Cloud Firestore могут включать как однопольные (автоматические), так и составные (созданные вручную) индексы. Вы можете изменить файл конфигурации Terraform, чтобы создать индекс для базы данных. Для автоматических и созданных вручную индексов используются разные типы ресурсов Terraform (google_firestore_index и google_firestore_field).

Индекс по одному полю (автоматический)

В следующем примере файла конфигурации Terraform создается индекс по одному полю name в коллекции chatrooms:

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 идентификатором своего проекта. Идентификаторы проектов должны быть уникальными.
  • Замените database-id идентификатором своей базы данных.

Составной (созданный вручную) индекс

В следующем примере файла конфигурации Terraform создается составной индекс для комбинации поля name и поля description в коллекции chatrooms:

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 идентификатором своего проекта. Идентификаторы проектов должны быть уникальными.
  • Замените database-id идентификатором своей базы данных.

Векторный индекс

В следующем примере файла конфигурации Terraform создается векторный индекс для поля embedding в коллекции chatrooms:

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 идентификатором своего проекта. Идентификаторы проектов должны быть уникальными.
  • Замените database-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

Проверить статус операции

Вместо того чтобы выводить список всех продолжительных операций, вы можете получить информацию об одной операции:

gcloud firestore operations describe operation-name

Оценка времени завершения

По мере выполнения операции проверяйте значение поля state, чтобы узнать ее общий статус.

Запрос статуса продолжительной операции также возвращает показатели workEstimated и workCompleted. Эти показатели возвращаются для количества документов. 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 для выполняемых операций.

Ошибки при создании индекса

При управлении индексами, созданными вручную, и исключениями для автоматических индексов могут возникать ошибки. Операция индексирования может завершиться неудачно, если Cloud Firestore столкнется с проблемой при индексировании данных. Чаще всего это означает, что вы достигли лимита на индексирование. Например, операция могла достичь максимального количества записей индекса на документ.

Если создать индекс не удастся, в консоли появится сообщение об ошибке. Убедитесь, что вы не превысили ограничения на индексирование, и повторите попытку.