Gerenciar índices

O Firestore garante o alto desempenho das consultas ao exigir um índice de todas elas. Os índices necessários para as consultas mais básicas são criados automaticamente para você. À medida que você usa e testa o aplicativo, o Cloud Firestore gera mensagens de erro para ajudar na criação de outros índices necessários. Nesta página, você entenderá como gerenciar índices de campo único e compostos.

Criar um índice inexistente usando uma mensagem de erro

Se você tentar executar uma consulta composta com uma cláusula de intervalo que não esteja mapeada a um índice atual, um erro será retornado. A mensagem desse erro inclui um link direto para você criar o índice ausente no Firebase console.

Abra o link gerado para o Firebase console, revise as informações preenchidas automaticamente e clique em Criar.

Papéis e permissões

Antes de criar um índice no Firestore, confirme se um dos seguintes papéis foi atribuído a você:

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

Se você tiver definido papéis personalizados, atribua todas as permissões a seguir para criar índices:

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

Usar o Console do Google Cloud Platform

No Console do Google Cloud Platform, é possível gerenciar isenções de indexação de campo único e índices compostos.

Criar um índice composto

Para criar manualmente um novo índice composto a partir do Console do GCP, faça isto:

  1. No Console do Google Cloud, acesse a página Bancos de Dados.

    Acessar "Bancos de dados"

  2. Selecione o banco de dados necessário na lista de bancos de dados.

  3. No menu de navegação, clique em Índices e na guia Composto.

  4. Clique em Criar índice.

  5. Insira um ID de coleção. Adicione os nomes dos campos que você quer indexar e um modo de índice para cada campo. Clique em Salvar índice.

Seu novo índice será exibido na lista de índices compostos, e o Firestore começará a criar seu índice. Quando o processo de criação terminar, você verá uma marca de seleção verde próxima ao índice.

Excluir um índice composto

Para excluir um índice composto, realize estas ações:

  1. No Console do Google Cloud, acesse a página Bancos de Dados.

    Acessar "Bancos de dados"

  2. Selecione o banco de dados necessário na lista de bancos de dados.

  3. No menu de navegação, clique em Índices e na guia Composto.

  4. Na lista de índices compostos, clique no botão Mais referente ao índice que você quer excluir. Clique em Excluir.

  5. Confirme que quer excluir o índice clicando em Excluir índice no alerta.

Adicionar uma isenção de índice de campo único

As isenções de índice de campo único permitem modificar configurações automáticas de índice para campos específicos em uma coleção. É possível adicionar uma isenção de campo único no console:

  1. No Console do Google Cloud, acesse a página Bancos de Dados.

    Acessar "Bancos de dados"

  2. Selecione o banco de dados necessário na lista de bancos de dados.

  3. No menu de navegação, clique em Índices e na guia Campo único.

  4. Clique em Adicionar isenção.

  5. Insira um ID da coleção e um caminho de campo.

  6. Selecione novas configurações de indexação para o campo. Ative ou desative os índices de campo único crescente, decrescente e de "matriz contém" atualizados automaticamente.

  7. Clique em Salvar isenção.

Adicionar uma isenção no nível da coleção

Para definir uma isenção de índice de campo único que se aplica a todos os campos em um ID de coleção:

  1. Clique em Adicionar isenção.
  2. Insira um ID da coleção para o grupo de coleções e defina Caminho do campo como *.

    Escolher campo para isenção

  3. Selecione as isenções de indexação que você quer aplicar a todos os campos no grupo de coleções.

  4. Clique em Salvar isenção.

Excluir uma isenção de índice de campo único

Para excluir uma isenção de índice de campo único, faça isto:

  1. No Console do Google Cloud, acesse a página Bancos de Dados.

    Acessar "Bancos de dados"

  2. Selecione o banco de dados necessário na lista de bancos de dados.

  3. No menu de navegação, clique em Índices e na guia Campo único.

  4. Na lista de isenções de índice de campo único, clique no botão Mais para isenção do que gostaria de excluir. Clique em Excluir.

  5. Confirme que você quer excluir a isenção clicando em Excluir no alerta.

Ao excluir uma isenção de campo único, o campo ou subcampo especificado usará as configurações de indexação herdadas. Os campos do documento são revertidos para as configurações automáticas de índice do seu banco de dados. Os subcampos de um mapa herdam qualquer isenção em campos pai antes de herdarem configurações automáticas de índice.

Na Firebase CLI

Também é possível implantar índices com a CLI do Firebase. Para começar, execute o comando firebase init firestore no diretório do projeto. Durante a configuração, a Firebase CLI gera um arquivo JSON com os índices padrão no formato correto. Edite o arquivo para adicionar mais índices e faça a implantação usando o comando firebase deploy.

Para implantar somente índices e regras do Firestore, adicione o sinalização --only firestore.

Se você fizer edições nos índices usando o Console do Firebase, atualize o arquivo de índices local. Consulte a referência de definição do índice JSON.

Usar o Terraform

Como criar índices no banco de dados

Os bancos de dados do Firestore podem incluir índices de campo único e compostos. É possível editar o arquivo de configuração do Terraform para criar um índice para o banco de dados. Os índices de campo único e compostos usam tipos de recursos do Terraform distintos.

Os índices do modo nativo do Firestore e do modo Datastore são compatíveis.

Índice de campo único

O exemplo de arquivo de configuração do Terraform a seguir cria um índice de campo único no campo name na coleção 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 {}
}
  • Substitua project-id pela ID do seu projeto. Os ID do projeto precisam ser exclusivos.
  • Substitua database-id pelo ID do banco de dados.

Índice composto

O exemplo de arquivo de configuração do Terraform a seguir cria um índice composto para uma combinação dos campos name e description na coleção 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"
  }

}
  • Substitua project-id pela ID do seu projeto. Os ID do projeto precisam ser exclusivos.
  • Substitua database-id pelo ID do banco de dados.

Índices do modo Datastore

Também é possível criar índices do modo Datastore usando o Terraform.

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"
}
Migrar de google_datastore_index

O recurso google_datastore_index foi descontinuado e não estará disponível no terraform-provider-google versão 6.0.0 ou posterior.

Se você estava usando o recurso google_datastore_index, migre para google_firestore_index. Para migrar, faça o seguinte:

  1. Crie um recurso google_firestore_index equivalente.
  2. Importe o índice do modo Datastore para o novo recurso.
  3. Remova as referências ao recurso google_datastore_index antigo.
  4. Remova o recurso google_datastore_index antigo do estado do Terraform.
  5. terraform apply está sendo executado para aplicar as mudanças.

Confira instruções mais detalhadas:

  1. Escreva um google_firestore_index substituto com base no recurso google_datastore_index atual. Veja as mudanças necessárias abaixo.
  2. Determine o caminho do recurso do Firestore do seu índice:

    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 '"')
    

    Substitua datastore-index-resource-name pelo nome do recurso do Terraform.

  3. Importe o índice do modo Datastore para o recurso google_firestore_index criado acima:

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

    Substitua firestore-index-resource-name pelo nome do Terraform do seu recurso atual.

    Para mais informações sobre a importação de recursos de índice do Firestore, consulte a documentação de referência do google_firestore_index.

  4. Exclua o recurso google_datastore_index atual do arquivo de configuração do Terraform.
  5. Remova o recurso google_datastore_index atual do estado do Terraform:

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

    Para mais informações sobre a remoção de recursos, consulte a página do Terraform sobre Como remover recursos.

  6. Execute terraform plan. Verifique a saída para confirmar que você não está criando nem destruindo recursos.

    Inspecione a saída para garantir que a importação foi concluída. Se a saída mostrar alguma alteração nos campos, verifique se essas alterações são intencionais. Se a saída incluir uma linha semelhante a:

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

    Em seguida, inspecione o arquivo de configuração do Terraform para saber se há algum erro.

  7. Quando estiver satisfeito com a saída do plano do Terraform, execute:

    terraform apply
    

  8. Traduzir o índice

    Para converter um recurso google_datastore_index para o recurso google_firestore_index equivalente, copie-o e faça as seguintes alterações:

    • Substitua google_datastore_index por google_firestore_index.
    • Substitua o nome do argumento kind por collection, mas mantenha o valor do argumento.
    • Substitua o nome do argumento ancestor por query_scope. Substitua o valor do argumento ALL_ANCESTORS por COLLECTION_RECURSIVE e qualquer outro valor por COLLECTION_GROUP. Se não houver um argumento ancestor, adicione um argumento query_scope com o valor COLLECTION_GROUP.
    • Adicione o argumento api_scope com o valor DATASTORE_MODE_API.
    • Para cada instância de properties, substitua por uma instância correspondente de fields. Substitua cada instância de name por field_path e cada instância de direction por order.

    Por exemplo, considere este recurso google_datastore_index:

    datastore.tf

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

    O recurso google_firestore_index equivalente seria:

    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"
      }
    }
    

    Tempo de criação do índice

    Para criar um índice, o Firestore precisa configurar o índice e, em seguida, preencher o índice com os dados existentes. O tempo de criação do índice é a soma do tempo de configuração e do tempo de preenchimento:

    • A configuração de um índice leva alguns minutos. O tempo de criação mínimo de um índice é de alguns minutos, mesmo para um banco de dados vazio.

    • O tempo de preenchimento depende da quantidade de dados no índice novo. Quanto mais valores de campo corresponderem à definição do índice, mais demorado será o preenchimento.

    As versões de índice são operações de longa duração.

    Depois de iniciar um build de índice, o Firestore atribui um nome exclusivo à operação. Os nomes das operações são prefixados com projects/[PROJECT_ID]/databases/(default)/operations/, por exemplo:

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

    No entanto, é possível deixar de fora o prefixo ao especificar um nome de operação para o comando describe.

    Como listar todas as operações de longa duração

    Para listar operações de longa duração, use o comando gcloud firestore operations list. Esse comando lista as operações contínuas e as concluídas recentemente. As operações são listadas por alguns dias após a conclusão:

    gcloud firestore operations list
    

    Verificar o status da operação

    Em vez de listar todas as operações de longa duração, é possível listar os detalhes de uma única operação:

    gcloud firestore operations describe operation-name

    Como estimar o tempo de conclusão

    Conforme sua operação é executada, consulte o valor do campo state para o status geral da operação.

    Uma solicitação para o status de uma operação de longa duração também retorna as métricas workEstimated e workCompleted. Essas métricas são retornadas para o número de documentos. workEstimated mostra o número total estimado de documentos que uma operação processará. workCompleted mostra o número de documentos processados até o momento. Após a conclusão da operação, workCompleted reflete o número total de documentos que foram realmente processados, o que pode ser diferente do valor de workEstimated.

    Divida workCompleted por workEstimated para ter uma estimativa aproximada do andamento. A estimativa pode ser imprecisa porque depende da coleção de estatísticas em atraso.

    Por exemplo, veja o status do progresso de uma criação de índice:

    {
      "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"
            }
           },
        },
        ...
    

    Quando uma operação for concluída, a descrição da operação conterá "done": true. Veja o valor do campo state para o resultado da operação. Se o campo done não for definido na resposta, seu valor será false. Não dependa da existência do valor done para operações em andamento.

    Erros na criação do índice

    Talvez você encontre erros na criação ao gerenciar índices compostos e isenções de índices de campo único. A indexação pode falhar se o Firestore encontrar um problema com os dados usados nessa operação. Isso costuma significar que você atingiu um limite de índice. Por exemplo, a operação pode ter atingido o número máximo de entradas de índice por documento.

    Se a criação do índice falhar, você verá a mensagem de erro no console. Verifique se você atingiu algum limite de índice. Depois, tente novamente a operação de indexação.