Migrar do App Engine Datastore para o Firestore no modo Datastore

Neste guia, você verá como migrar do App Engine Datastore para o Firestore no modo Datastore, também conhecido como Datastore.

O Firestore no modo Datastore é semelhante ao Datastore do App Engine, porque ambos se referem ao mesmo serviço subjacente do Datastore. Embora o App Engine Datastore só possa ser acessado por meio dos serviços em pacote legados do App Engine, o Firestore no modo Datastore é um produto independente do Google Cloud acessado pelas bibliotecas de cliente do Cloud.

O Firestore no modo Datastore também oferece um nível gratuito e permite gerenciar um banco de dados de documentos NoSQL altamente escalonável e oferece a flexibilidade de migrar para o Cloud Run ou outra plataforma de hospedagem de apps do Google Cloud no futuro.

Antes de começar

  1. Analise os diferentes modos de banco de dados do Firestore para garantir que você entenda o melhor caso de uso para seu app. Este guia explica como migrar para o modo Datastore.

  2. Analise e entenda os preços e as cotas do modo Datastore no Datastore.

    O Firestore no modo Datastore oferece uso gratuito com limites diários e operações ilimitadas de armazenamento, leitura e gravação para contas pagas. Enquanto os aplicativos do App Engine estão desativados, eles não recebem tráfego, mas o uso do Datastore pode ser cobrado se exceder os limites de cota gratuitos.

  3. Ative as seguintes APIs no projeto que contém o aplicativo:

    • API Artifact Registry para armazenar e gerenciar seus artefatos de versão
    • API Cloud Build para criar, testar e implantar o aplicativo continuamente.
    • API do Cloud Datastore para migrar do Datastore do App Engine para o Firestore no modo Datastore.

      Ativar APIs

  4. Ter um aplicativo do App Engine em execução no Java 8 ou 11 conectado ao serviço Datastore do App Engine.

Visão geral do processo

Em um nível superior, o processo de migração do App Engine para o Firestore em modo Datastore consiste nas seguintes etapas:

  1. Atualizar os arquivos de configuração
  2. Atualizar o app Java
    1. Atualizar as instruções de importação
    2. Modificar a forma como o app acessa o serviço do Datastore
    3. Receber uma chave gerada pelo Datastore
    4. Modificar a criação da entidade
  3. Confirmar sua transação
  4. Resultados da consulta

Atualizar os arquivos de configuração

Atualize seus arquivos de configuração para usar as bibliotecas de cliente do modo Datastore.

Atualize o arquivo pom.xml do seu aplicativo Java do valor de referência:

  1. Remova as importações appengine-api-1.0-sdk do SDK do App Engine, como a seguir:

    <dependency>
      <groupId>com.google.appengine</groupId>
      <artifactId>appengine-api-1.0-sdk</artifactId>
      <version>2.0.4</version>
    </dependency>
    
  2. Adicione o cliente Datastore, desta maneira:

    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-datastore</artifactId>
      <!-- Use latest version -->
      <version>2.2.9</version>
    </dependency>
    

Atualizar seu aplicativo Java

Atualizar instruções de importação

Modifique os arquivos do aplicativo atualizando as linhas de importação e inicialização:

  1. Remova as seguintes declarações de importação do App Engine para com.google.appengine.api.datastore.* do App Engine Datastore:

      import com.google.appengine.api.datastore.DatastoreService;
      import com.google.appengine.api.datastore.DatastoreServiceFactory;
      import com.google.appengine.api.datastore.Entity;
      import com.google.appengine.api.datastore.FetchOptions;
      import com.google.appengine.api.datastore.Query;
    
  2. Adicione as seguintes importações com.google.cloud.datastore.* do Firestore no modo Datastore:

      import com.google.cloud.Timestamp;
      import com.google.cloud.datastore.Datastore;
      import com.google.cloud.datastore.DatastoreOptions;
      import com.google.cloud.datastore.Entity;
      import com.google.cloud.datastore.Key;
      import com.google.cloud.datastore.FullEntity;
      import com.google.cloud.datastore.KeyFactory;
      import com.google.cloud.datastore.Query;
      import com.google.cloud.datastore.QueryResults;
      import com.google.cloud.datastore.StructuredQuery;
    

Modificar como o app acessa o serviço do Datastore

O Firestore no modo Datastore usa a classe Datastore em vez de DatastoreService. Para modificar a forma como seu aplicativo acessa o serviço do Datastore:

  1. Encontre as linhas que usam o método DatastoreServiceFactory.getDatastoreService(), como o seguinte:

    // Initialize a client
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    
  2. Substitua o DatastoreServiceFactory.getDatastoreService() pelo método DatastoreOptions.getDefaultInstance().getService(), como este:

    // Initialize a client
    Datastore datastore = DatastoreOptions.getDefaultInstance().getService();
    

Receber uma chave gerada pelo Datastore

Depois de inicializar um cliente, receba sua chave criando um novo KeyFactory do Kind apropriado e, em seguida, faça com que o Datastore gere um para você. Para conseguir uma chave gerada pelo Datastore:

  1. Crie um newKeyFactory.

  2. Chame o método setKind() para determinar o kind da entidade usada para categorizar as consultas.

  3. Anexe o método newKey() para gerar uma chave do Datastore:

    //Prepare a new entity
    String kind = "visit";
    Key key = datastore.allocateId(datastore.newKeyFactory().setKind(kind).newKey());
    

Modificar a criação da entidade

Depois de conseguir uma chave do Datastore, crie entidades usando os seguintes métodos:

  1. Use Entity.newBuilder e transmita a chave gerada pelo Datastore.

    Encontre as linhas que usam a chamada de construtor Entity, como esta:

    Entity visit = new Entity(kind);
    

    Substitua a chamada de construtor Entity pela chamada de construtor Entity.newBuilder, da seguinte maneira:

    Entity visit = Entity.newBuilder(key);
    
  2. Use o método set para definir propriedades em entidades.

    O primeiro parâmetro é a propriedade pretendida, e o segundo é o valor. No caso da propriedade timestamp, o valor é um Timestamp em vez de um Instant.toString().

    Encontre as linhas que usam o método setProperty, como a seguir:

    visit.setProperty("user_ip", userIp);
    visit.setProperty("timestamp", Instant.now().toString());
    

    Substitua o método setProperty pelo método set, da seguinte maneira:

    Entity visit = Entity.newBuilder(key).set("user_ip", userIp).set("timestamp", Timestamp.now()).build();
    

Confirmar sua transação

A biblioteca de cliente do Firestore no modo Datastore usa o método add() para confirmar uma transação. Para confirmar sua transação:

  1. Encontre linhas que usam o método put(), como a seguir:

    // Save the entity
    datastore.put(visit);
    
  2. Substitua o método put() pelo método add(), da seguinte maneira:

    // Save the entity
    datastore.add(visit);
    

Resultados da consulta

As consultas recuperam entities que atendem a um conjunto específico de condições. Você pode usar os seguintes métodos para exibir resultados:

  • O método OrderBy exibe os resultados em ordem crescente ou decrescente.

  • O método Limit limita o número máximo de resultados buscados usando no mesmo builder.

A consulta usa um método de padrão de builder com a variável kind. A variável kind é definida como Visit na etapa Receber uma chave gerada pelo Datastore.

Para recuperar os 10 primeiros resultados:

  1. Encontre linhas que usam o método addSort(), como a seguir:

      // Retrieve the last 10 visits from the datastore, ordered by timestamp.
      Query query = new Query(kind).addSort("timestamp", Query.SortDirection.DESCENDING);
      List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));
    
  2. Substitua o método addSort() pelo método setOrderBy() e anexe o método setLimit(), desta forma:

    // Retrieve the last 10 visits from the datastore, ordered by timestamp.
    Query<Entity> query = Query.newEntityQueryBuilder()
                            .setKind(kind)
                            .setOrderBy(StructuredQuery.OrderBy.desc("timestamp"))
                            .setLimit(10)
                            .build();
    
  3. Quando a consulta estiver pronta, execute o código usando datastore.run() e colete os resultados em uma coleção QueryResultsEntity.

    O objeto QueryResults resultante é um iterador com uma função hasNext().

  4. Verifique se o conjunto de resultados tem um objeto next para processamento, em vez de repetir a lista de resultados. Por exemplo:

    QueryResults<Entity> results = datastore.run(query);
    
          resp.setContentType("text/plain");
          PrintWriter out = resp.getWriter();
          out.print("Last 10 visits:\n");
          while (results.hasNext()) {
              Entity entity = results.next();
              out.format(
                      "Time: %s Addr: %s\n", entity.getTimestamp("timestamp"), entity.getString("user_ip"));
          }
    

Exemplos

Para ver um exemplo de como migrar um app Java 8 para o Firestore no modo Datastore, compare o exemplo de código do App Engine Datastore para Java 8 e o exemplo de código do Firestore no modo Datastore no GitHub.

O que vem em seguida?