1. 概要
この一連の Codelab(ご自分のペースで進められる実践型のチュートリアル)は、一連の移行についてガイダンスを実施することにより、Google App Engine(標準)のデベロッパーがアプリをモダナイズできるよう支援することを目的としています。このような移行のほとんどは、元のランタイム バンドル サービスからの移行です。理由は、次世代のランタイムが柔軟性に富み、ユーザーにさまざまなサービス オプションが提供されるためです。アプリを最新化するもう 1 つの方法は、新しいプロダクトにアップグレードすることです。これがこの Codelab のテーマです。
Cloud NDB または Cloud Datastore クライアント ライブラリを使用して Datastore にアクセスしている App Engine ユーザーは、そのまま使用でき、さらに移行する必要はありません。ただし、Cloud Firestore は、Firebase リアルタイム データベースの機能を備えた、最新のスケーラブルで高可用性の NoSQL データストアです。
Firestore の機能を利用するために Firestore を使用したいと考えているデベロッパーや、移行について詳しく知りたいと考えているデベロッパーは、このガイドが役に立ちます。このチュートリアルでは、Cloud Datastore を使用する App Engine アプリを Cloud Firestore に移行する方法について説明します。
方法を学ぶ対象
- Datastore と Firestore の違いを認識する
- Cloud Datastore から Cloud Firestore に移行する
必要なもの
- 次の対象を使用した Google Cloud Platform プロジェクト。
- 基本的な Python スキル
- 一般的な Linux コマンドに関する実践的な知識
- App Engine アプリの開発とデプロイに関する基礎知識
- この演習(モジュール 6)を開始する前に、モジュール 3 Codelab(Python 3 への移植を含む)を完了することをおすすめします。
- 正常に機能する Module 3 Cloud Datastore Python 3 App Engine アプリ。
アンケート
この Codelab をどのように使用されますか?
2. 背景情報
App Engine の Datastore は 2013 年に独自のプロダクト(Google Cloud Datastore)となり、現在では App Engine の外部のデベロッパーもアクセスできるようになっています。翌年、Firebase は Google に買収されました。当時、Firebase はリアルタイム データベースで知られていました。
その後数年間、Firebase チームと Cloud Datastore チームは、Firebase の一部の機能を Datastore に統合する作業を進めてきました。その結果、2017 年に次世代の Cloud Datastore がリリースされました。一部の Firebase 機能の継承を反映するため、Cloud Firestore にリブランディングされました。
Cloud Firestore が Google Cloud プロジェクトのデフォルトの NoSQL ストレージ メカニズムになりました。新しいアプリは Cloud Firestore をネイティブに使用できますが、既存の Datastore データベースは内部で Firestore に変換され、Datastore オペレーションとの互換性を維持するために「Datastore モードの Firestore」として動作するようになりました。そのため、アプリケーションはこれらのモードのいずれか 1 つで Cloud Firestore を運用できますが、設定後に変更することはできません。
現在、ユーザーが新しいプロジェクトを作成して NoSQL ソリューションを選択すると、Datastore モードの Firestore またはネイティブ モードの Firestore のいずれかを選択するように求められます。ユーザーが Datastore エンティティを追加すると、Firestore に変更できなくなります。同様に、Firestore ネイティブ モードを選択すると、Datastore(または Datastore モードの Firestore)に戻すことはできません。詳細については、ドキュメントの Datastore モードの Cloud Firestore とネイティブ Firestore モードの選択をご覧ください。アプリを Firestore に移行するには、新しいプロジェクトを作成し、Datastore をエクスポートして Firestore にインポートする必要があります。このチュートリアルでは、Cloud Datastore と Cloud Firestore の使用の違いについて説明します。
この移行はユーザーが実行することを想定していないため、移行は任意です。Cloud Firestore をネイティブに使用することには、クライアント認証、Firebase ルールの統合、Firebase リアルタイム データベースなど、明らかな利点がありますが、移行手順は「不便」です。
- 現在のアプリのプロジェクトとは別のプロジェクトを使用する必要があります。
- アプリで Datastore エンティティを追加したプロジェクトをネイティブ モードの Firestore に切り替えることはできません
- 同様に、ネイティブ モードの Firestore を選択したプロジェクトを Datastore モードの Firestore に戻すことはできません。
- あるプロジェクトから別のプロジェクトにデータをストリーミングできる移行ツールはありません。
- 名前空間や書き込みスループットの向上(>10,000 回/秒)など、Datastore の重要な機能の一部は Firestore では利用できません。
- エクスポート ツールとインポート ツールは、「プリミティブ」と「すべてまたはなし」のシナリオです。
- アプリに多数の Datastore エンティティがある場合、エクスポートしてから Firestore にインポートするのに数時間かかることがあります。
- この間、アプリケーションやサービスはデータの書き込みや更新を行うことができません。
- 移行アクティビティは通常の使用量にカウントされます。費用を最小限に抑えるため、移行アクティビティを分散することをおすすめします(可能であれば、1 日の割り当てに分散します)。
- 新しいサービスは別のプロジェクトで実行されるため、DNS 更新が伝播されるまでの時間が必要です。
- Datastore と Firestore のデータモデルは似ていますが、異なるため、移行にはアプリやサービスの動作方法の更新が必要です。
- Datastore の祖先クエリは、Firestore のコレクション クエリ(デフォルト)になりました
- Datastore の広範なタイプのクエリは、Firestore のコレクション グループ クエリです
- インデックスと処理が異なるなど。
ただし、移行を検討しているアプリが比較的単純な場合、移行のシミュレーションを準備している場合、または Datastore と Firestore の違いについて学習するためにこのページにアクセスした場合は、このまま読み進めてください。
Python 2 ユーザー: この移行に関するオプションのコードラボは Python 3 でのみ提供されますが、Cloud Firestore は 2.x もサポートしているため、ユーザーは使用方法の違いを補完できます。たとえば、Firestore レコードでは Unicode 文字列(バイト文字列ではなく)が使用されるため、Python 2 文字列リテラルには u'' 先頭インジケーターが必要です。つまり、2.x store_visit() 関数は次のようになります。
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
それ以外は、クライアント ライブラリは同様に動作します。考慮すべきもう 1 つの問題は、2.x Cloud Firestore ライブラリは開発が「凍結」されているため、新しい機能は 3.x Firestore クライアント ライブラリでのみ利用可能になることです。
この移行を進めるにあたり、このチュートリアルの主な手順は次のとおりです。
- セットアップ / 事前作業
- Cloud Firestore ライブラリを追加する
- アプリケーション ファイルの更新
3. セットアップ/事前作業
チュートリアルの主要部分に進む前に、まずプロジェクトをセットアップし、コードを取得してから、ベースライン アプリをデプロイします。これで、作業コードを使って作業を開始できます。
1. プロジェクトのセットアップ
モジュール 3 Codelab で使用したプロジェクトと同じプロジェクトを再利用することをおすすめします。または、新しいプロジェクトを作成するか、別の既存のプロジェクトを再利用することもできます。プロジェクトにアクティブな請求先アカウントがあり、App Engine(アプリ)が有効になっていることを確認します。
2. ベースライン サンプルアプリを入手する
この Codelab の前提条件の 1 つは、機能するモジュール 3 のサンプルアプリを用意することです。まだお持ちでない場合は、先に進む前にモジュール 3 のチュートリアル(上のリンク)を完了してください。すでに内容に精通している場合は、以下のモジュール 3 のコーディングから開始してください。
ご自分のコードと Google で用意したコードのいずれを使用される場合も、モジュール 3 のコードから開始します。このモジュール 6 の Codelab では、各ステップについて順を追って説明します。完了すると、終了ポイントのコードが次のように表示されます。(このチュートリアルは Python 3 でのみ使用できます)。
- 開始: モジュール 3 リポジトリ
- 終了: モジュール 6 リポジトリ
- リポジトリ全体(クローン作成または ZIP をダウンロード)
モジュール 3 ファイル(ご自身または Google のもの)のディレクトリは、次のようになります。
$ ls
README.md main.py templates
app.yaml requirements.txt
3. モジュール 3 アプリを(再)デプロイする
この段階で実施する必要がある残りの事前作業のステップ:
gcloudコマンドライン ツールについて復習する(必要な場合)- モジュール 3 コードを App Engine に(再)デプロイします(必要な場合)。
各手順を正常に実行して、動作していることを確認したら、このチュートリアルに進み、構成ファイルを使用して作業を開始します。
Python 2 の要件
app.yamlが(引き続き)サードパーティ バンドル パッケージ(grpcioとsetuptools)を参照していることを確認します。appengine_config.pyが引き続きpkg_resourcesとgoogle.appengine.ext.vendorを使用して、アプリをサードパーティ リソースに向けるようにします。- 次のセクションで
requirements.txtを更新する際は、google-cloud-firestore==1.9.0を使用する必要があります。これは、Python Firestore クライアント ライブラリの 2.x 互換の最終バージョンです。requirements.txtにgoogle-cloud-coreのエントリがある場合は、そのままにします。libを削除し、pip install -t lib -r requirements.txtで再インストールします。
4. 構成ファイルを更新する(Cloud Firestore ライブラリを追加する)
セットアップ以外に必要な次の手順は、構成を更新してからアプリケーション ファイルを更新することです。前者については、requirements.txt ファイルでのパッケージのマイナーな入れ替えのみが構成の変更となるため、ここでそれを行います。
requirements.txt の google-cloud-datastore の行を google-cloud-firestore に置き換えます。
Flask==1.1.2
google-cloud-firestore==2.0.2
各ライブラリの最新バージョンを使用することをおすすめします。上記のバージョン番号は、このドキュメントの作成時点での最新バージョンです。FINISH リポジトリ フォルダのコードは頻繁に更新されるため、新しいバージョンが存在する可能性があります。
他の構成変更はないため、app.yaml と templates/index.html はそのままです。
5. アプリケーション ファイルを更新する
アプリケーション ファイルは main.py の 1 つだけなので、このセクションの変更はすべてそのファイルにのみ影響します。
1. インポート
パッケージのインポートを切り替えるには、datastore から firestore に小規模な変更を行います。
- 変更前:
from google.cloud import datastore
- 変更後:
from google.cloud import firestore
2. Firestore へのアクセス
Flask を初期化した後、Firestore クライアントを作成します。上記と同様の変更をクライアントの初期化に対して行います。
- 変更前:
app = Flask(__name__)
ds_client = datastore.Client()
- 変更後:
app = Flask(__name__)
fs_client = firestore.Client()
Cloud NDB から Cloud Datastore への移行を行うことで、Cloud Firestore への移行に必要な作業はすでに完了しています。Datastore では、共通のプロパティで構成されたエンティティの形式でデータレコードを作成し、キーでグループ化します。Firestore のデータレコードはドキュメントです。ドキュメントは Key-Value ペアで構成され、コレクションにグループ化されます。Datastore から移行する場合は、これらの違いを考慮する必要があります。これらの違いは、データレコードの作成時とクエリ時に顕在化します。結果は、Datastore コードの複雑さによって異なる場合があります。
Datastore の場合は、エンティティ タイプに基づいて、フィルタリングと並べ替えの条件とともにクエリを作成します。Firestore の場合、データのクエリも同様です。次のクエリ値、クライアント(それぞれ ds_client または fs_client)、インポートを想定して、簡単な例を見てみましょう。
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Datastore の場合、2020 年 10 月 1 日より新しい Visit エンティティを最新の 10 件について降順でクエリします。
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Firestore で同じ操作を Visit コレクションから行う場合:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
サンプルアプリのクエリはより単純です(「WHERE」句がありません)。Cloud Datastore のコードを振り返ってみましょう。
- 変更前:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Firestore に移行すると、新しいドキュメントの作成はエンティティと似ており、クエリは前述のとおりです。
- 変更後:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
メイン関数 root() と index.html テンプレート ファイルは変更されません。変更内容を再確認し、保存、デプロイ、検証します。
6. 概要/クリーンアップ
アプリケーションのデプロイ
gcloud app deploy を使用してアプリを再デプロイし、アプリが動作していることを確認します。これで、コードはモジュール 6 リポジトリ(または 2.x バージョン)の内容と一致するはずです。
先行するいずれの Codelab の取り組みも行わずにこのシリーズに進んだ場合、アプリ自体は変更されません。このアプリは、メインのウェブページ(/)へのすべての訪問を登録します。一定回数以上サイトにアクセスすると、ウェブページは次のように表示されます。

これで、オプションのモジュール 6 の移行は完了です。これは、App Engine データ ストレージに関する限り、最後の移行の 1 つである可能性が高いです。移行の別の方法として、まだアプリをコンテナ化していない場合は、Cloud Run 用にコンテナ化することを検討できます(下記のリンク先の Codelab のモジュール 4 と 5 をご覧ください)。
オプション: クリーンアップ
次の移行 Codelab に進む準備が整うまで、課金されるのを回避するためのクリーンアップを行うにはどうすればよいでしょうか。既存のデベロッパーの方は、App Engine の料金に関する情報に関する最新の内容をすでにご存じと思われます。
オプション: アプリを無効にする
次のチュートリアルに進む準備がまだ完了していない場合は、アプリを無効にすることで課金されないようにできます。次の Codelab に進む準備ができた時点で、再度有効にできます。アプリが無効になっている間、料金のかかるトラフィックは発生しません。ただし、もう 1 つの課金対象は、Firestore の使用量です。無料割り当て量を超過した場合は課金が発生するため、上限を超えないよう削除してください。
ただし、移行を続けず、すべてを完全に削除する場合は、プロジェクトをシャットダウンしてください。
次のステップ
このチュートリアルのほかに、移行モジュールの Codelab がいくつかあります。
- モジュール 7: App Engine の push タスクキュー([push] タスクキューを使用する場合に必要)
- App Engine
taskqueueプッシュタスクをモジュール 1 アプリに追加する - モジュール 8 で Cloud Tasks に移行するユーザーの準備を行う
- App Engine
- モジュール 4: Docker を使用して Cloud Run に移行する
- Docker を使用して、Cloud Run で実行できるようにアプリをコンテナ化します。
- この移行により、Python 2 を引き続き使用できます。
- モジュール 5: Cloud Build を使用した Cloud Run への移行。
- Cloud Build を使用して Cloud Run で実行するようにアプリをコンテナ化します。
- Docker、コンテナ、
Dockerfileについての知識は何も必要ありません。 - すでに Python 3 に移行しているアプリが必要です(Buildpacks では Python 2 はサポートされていません)。
7. 参考情報
App Engine 移行モジュールの Codelab に関する問題 / フィードバック
この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:
移行に関するリソース
モジュール 3(開始)とモジュール 6(終了)のリポジトリ フォルダへのリンクを以下の表に示します。また、これらのファイルには、すべての App Engine 移行のリポジトリからアクセスすることもできます。このクローンの作成や ZIP ファイルのダウンロードも可能です。
Codelab | Python 2 | Python 3 |
(コード) | ||
モジュール 6 | 該当なし |
App Engine リソース
この特定の移行に関する追加リソースは以下のとおりです。
- Python Cloud Datastore と Cloud Firestore のリファレンス
- Python 3 および GAE 次世代ランタイムへの移行
- 全般