從 App Engine Datastore 遷移至 Datastore 模式的 Firestore

本指南說明如何從 App Engine Datastore 遷移至 Firestore (Datastore 模式) (也稱為 Datastore)。

Datastore 模式下的 Firestore 與 App Engine Datastore 類似,因為兩者都會參照相同的基礎 Datastore 服務。雖然 App Engine Datastore 只能透過 App Engine 舊版套裝服務存取,但 Datastore 模式的 Firestore 是可透過 Cloud 用戶端程式庫存取的獨立 Google Cloud 產品。

Datastore 模式的 Firestore 也提供免費方案,可讓您管理高度可擴充的 NoSQL 文件資料庫,並在日後靈活遷移至 Cloud Run 或其他 Google Cloud 應用程式代管平台。

事前準備

  1. 請詳閱不同 Firestore 資料庫模式,確保您瞭解應用程式的最佳用途。請注意,本指南將說明如何遷移至 Datastore 模式。

  2. 查看並瞭解 Firestore (Datastore 模式) 的定價配額

    Firestore (Datastore 模式) 提供免費用量,但設有每日上限,付費帳戶則可享有無限的儲存空間、讀取和寫入作業。在 App Engine 應用程式停用期間,不會產生任何流量費用,但如果 Datastore 用量超出免費配額限制,就可能會產生費用。

  3. 在包含應用程式的專案中啟用下列 API:

    • Artifact Registry API (用於儲存及管理建構作業構件)
    • 使用 Cloud Build API 持續建構、測試及部署應用程式。
    • Cloud Datastore API,可從 App Engine 內含的 Datastore 遷移至 Datastore 模式的 Firestore。

      啟用 API

  4. 擁有執行 Java 8 或 11 且已連線至 App Engine Datastore 服務的現有 App Engine 應用程式。

流程總覽

從 App Engine Datastore 遷移至 Datastore 模式的 Firestore 大致包含以下步驟:

  1. 更新設定檔
  2. 更新 Java 應用程式
    1. 更新匯入陳述式
    2. 修改應用程式存取 Datastore 服務的方式
    3. 取得 Datastore 產生的索引鍵
    4. 修改實體建立程序
  3. 提交交易
  4. 查詢結果

更新設定政策

更新設定檔,以便使用 Datastore 模式用戶端程式庫

更新基準 Java 應用程式的 pom.xml 檔案:

  1. 移除 App Engine SDK appengine-api-1.0-sdk 匯入作業,如下所示:

    <dependency>
      <groupId>com.google.appengine</groupId>
      <artifactId>appengine-api-1.0-sdk</artifactId>
      <version>2.0.4</version>
    </dependency>
    
  2. 新增 Datastore 用戶端,如下所示:

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

更新 Java 應用程式

更新匯入陳述式

更新匯入和初始化行來修改應用程式檔案:

  1. 移除下列 App Engine 匯入陳述式,以便使用 App Engine Datastore com.google.appengine.api.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. 新增下列 Datastore 模式的 Firestore com.google.cloud.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;
    

修改應用程式存取 Datastore 服務的方式

Datastore 模式的 Firestore 會使用 Datastore 類別,而非 DatastoreService。如要修改應用程式存取 Datastore 服務的方式,請按照下列步驟操作:

  1. 找出使用 DatastoreServiceFactory.getDatastoreService() 方法的行,如下所示:

    // Initialize a client
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    
  2. DatastoreServiceFactory.getDatastoreService() 替換為 DatastoreOptions.getDefaultInstance().getService() 方法,如下所示:

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

取得 Datastore 產生的金鑰

初始化用戶端後,請建立適當 Kind 的新 KeyFactory 來取得金鑰,然後讓 Datastore 為您產生金鑰。如要取得 Datastore 產生的金鑰,請按照下列步驟操作:

  1. 建立 newKeyFactory

  2. 呼叫 setKind() 方法,判斷用於查詢分類的實體的 kind

  3. 附加 newKey() 方法以產生 Datastore 鍵:

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

修改實體建立作業

取得 Datastore 鍵後,請使用下列方法建立實體:

  1. 使用 Entity.newBuilder,並傳遞 Datastore 產生的鍵

    找出使用 Entity 建構函式呼叫的程式碼行,如下所示:

    Entity visit = new Entity(kind);
    

    Entity 建構函式呼叫替換為 Entity.newBuilder 建構函式呼叫,如下所示:

    Entity visit = Entity.newBuilder(key);
    
  2. 使用 set 方法設定實體的屬性。

    第一個參數是預期的屬性,第二個則是值。在 timestamp 屬性的情況下,值為 Timestamp,而非 Instant.toString()

    找出使用 setProperty 方法的行,如下所示:

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

    setProperty 方法替換為 set 方法,如下所示:

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

提交交易

Datastore 模式的 Firestore 用戶端程式庫會使用 add() 方法來提交交易。如要提交交易,請按照下列步驟操作:

  1. 找出使用 put() 方法的行,如下所示:

    // Save the entity
    datastore.put(visit);
    
  2. put() 方法替換為 add() 方法,如下所示:

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

查詢結果

查詢會擷取符合一組特定條件的 entities。您可以使用下列方法顯示結果:

  • OrderBy 方法會依遞增或遞減順序顯示結果。

  • Limit 方法會限制在同一個建構工具中使用 擷取的結果數量上限。

查詢會使用建構工具模式方法搭配 kind 變數。在「取得 Datastore 產生的金鑰」步驟中,kind 變數已設為 Visit

如要擷取前 10 筆結果,請按照下列步驟操作:

  1. 找出使用 addSort() 方法的行,如下所示:

      // 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. addSort() 方法替換為 setOrderBy() 方法,並附加 setLimit() 方法,如下所示:

    // 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. 查詢完成後,請使用 datastore.run() 執行程式碼,並在 QueryResultsEntity 集合中收集結果。

    產生的 QueryResults 物件是含有 hasNext() 函式的疊代器。

  4. 請檢查結果集是否有 next 物件可供處理,而非循環處理結果清單。例如:

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

範例

如要查看如何將 Java 8 應用程式遷移至 Datastore 模式的 Firestore 的範例,請比較 GitHub 中的 App Engine Datastore for Java 8 程式碼範例Datastore 模式的 Firestore 程式碼範例

後續步驟