Google Datastore NDB クライアント ライブラリを使用すると、App Engine Python アプリから Datastore に接続できます。NDB クライアント ライブラリは従来の DB データストア ライブラリを基盤として、次のデータストア機能が追加されています。
- エンティティでネスト構造を使用できるようにする
StructuredProperty
クラス。 - 統合された自動キャッシュ。これは通常、インコンテキスト キャッシュや Memcache を介して高速かつ低負荷の読み取りを可能にします。
- 同期 API に加えて、同時アクション用の非同期 API もまたサポートされます。
このページでは、App Engine NDB クライアント ライブラリの概要について説明します。Python 3 をサポートする Cloud NDB に移行する方法については、Cloud NDB への移行をご覧ください。
エンティティ、キー、プロパティの定義
Datastore には、「エンティティ」と呼ばれるデータ オブジェクトが格納されます。各エンティティには 1 つ以上の「プロパティ」があります。プロパティは、サポートされるいずれかのデータ型を持つ名前付きの値です。たとえば、文字列、整数、別のエンティティへの参照などをプロパティとして設定できます。
各エンティティは「キー」、つまりアプリケーション データストア内で一意の識別子によって区別されます。1 つのキーが別のキーの「親」となることがあります。場合によっては、親自体にも親があり、さらにその親そのまた親と続いていくこともあります。このような親子関係の最上位にある、親を持たないキーは、「ルート」と呼ばれます。
同じルートに由来するキーを持つすべてのエンティティは、「エンティティ グループ」または「グループ」を形成します。互いに異なるグループに属する複数のエンティティを変更した場合、「無秩序」になるエラーが発生したように見えることがあります。アプリケーションのセマンティクスでこれらのエンティティが互いに無関係な場合は、問題ありません。しかし、いくつかのエンティティの変更に一貫性が必要な場合は、アプリケーションでこれらのエンティティを作成するときに同じグループに含めるべきです。
次に示すエンティティの関係図とコードサンプルでは、Guestbook
の中に複数の Greetings
が含まれ、それぞれに content
および date
プロパティが付属しています。
データを格納するためのモデルの使用
モデルはエンティティの種類を記述するクラスで、エンティティのプロパティの構成や種類などを含んでいます。これは、おおまかに言って SQL のテーブルとほぼ同じです。モデルのクラス コンストラクタを呼び出してエンティティを作成し、その後 put()
メソッドを呼び出してエンティティを保存できます。
クエリとインデックス
アプリケーションは、フィルタに合致するエンティティを見つけるためにクエリを実行できます。
通常の NDB クエリは、種類によってエンティティのフィルタリングを行います。クエリでは、エンティティ プロパティの値とキー、並べ替え順序のフィルタを指定することもできます。特定のエンティティが、フィルタと並べ替え順序のすべてのプロパティに関して少なくとも 1 つの値(null も可能)を持ち、しかもプロパティ値がすべてのフィルタ基準を満たす場合には、そのエンティティが結果として返されます。
各クエリは 1 つのインデックス(つまりクエリ結果を適切な順序で並べたテーブル)を使用します。基盤となるデータストアは、単純なインデックス(1 つのプロパティのみを使用するインデックス)を自動的にいくつか保持します。
また、構成ファイル index.yaml
内に複雑なインデックスを定義します。開発用ウェブサーバーは、インデックスがまだ構成されていないクエリが検出されると、このファイルに推奨を自動的に追加します。
アプリケーションをアップロードする前にこのファイルを編集して、インデックスを手動で調整できます。gcloud app deploy index.yaml
を実行することにより、アプリケーションのアップロードとは別個にインデックスを更新できます。
データストアに大量のエンティティがある場合、新しいインデックスを作成するのに時間がかかります。この場合、新しいインデックスを使用するコードをアップロードする前に、インデックス定義を更新することをおすすめします。管理コンソールを使用すると、インデックスの作成がいつ終了したかを検知できます。
インデックス メカニズムはさまざまなクエリをサポートしているため、ほとんどのアプリケーションに適しています。ただし、他のデータベース テクノロジーで一般にサポートされているいくつかの種類のクエリが、サポートされていません。特に、結合がサポートされていません。
NDB の書き込みを理解する: commit、キャッシュの無効化、適用
NDB がデータを書き込む手順は次のとおりです。
- commit フェーズで、基盤データストア サービスが変更を記録します。
- 影響を受けるエンティティのキャッシュを NDB が無効にします。こうして、その後の読み取りではキャッシュから古い値を読み取るのではなく、基盤データストアから読み取ってキャッシュに入れます。
- 最後に(おそらく数秒後に)、基盤データストアが変更を適用します。それによって、変更がグローバル クエリで認識でき、結果整合性のある読み取りを実現します。
データを書き込む NDB 関数(put()
など)は、キャッシュが無効になった後に返されます。適用フェーズは非同期的に発生します。
commit フェーズで障害が発生すると自動的に再試行されますが、障害が続けて発生する場合はアプリケーションが例外を受け取ります。commit フェーズが成功して適用が失敗した場合、次のいずれかが発生すると、適用フェーズがロール フォワードされて完了します。
- 定期的なデータストアの「スイープ」により、未完了の commit ジョブをチェックし、適用します。
- 影響を受けるエンティティ グループ内で、それ以降に書き込み、トランザクション、または強い整合性のある読み取りが発生すると、読み込み、書き込み、またはトランザクションの前に未適用の変更が適用されます。
この動作は、アプリケーションに対してデータがいつ、どのように表示されるかに影響を与えます。NDB 関数が結果を返した後、数百ミリ秒ほどの間は、基盤データストアに対して変更が必ずしも完全に適用されない可能性があります。変更が適用されている最中に実行された非祖先クエリでは、非整合状態が見られることがあります(つまりすべての変更ではなく、一部の変更のみが適用された状態)。
トランザクションとデータのキャッシュ
NDB クライアント ライブラリは、複数のオペレーションを 1 回のトランザクションとしてグループ化できます。トランザクション内のすべてのオペレーションが成功しない限り、そのトランザクションは成功になりません。オペレーションが 1 つでも失敗すると、トランザクションは自動的にロールバックされます。この機能は、複数のユーザーが同じデータに同時にアクセスしたり操作したりする可能性がある分散型ウェブ アプリケーションの場合に特に役立ちます。
NDB は、データの「ホットスポット」用のキャッシュ サービスとして Memcache を使用します。アプリケーションがいくつかのエンティティを頻繁に読み取る場合、NDB はキャッシュからそれらを素早く読み取ることができます。
NDB での Django の使用
Django ウェブ フレームワークとともに NDB を使用するには、Django の settings.py
ファイルの.MIDDLEWARE_CLASSES
エントリに google.appengine.ext.ndb.django_middleware.NdbDjangoMiddleware
を追加します。他のすべてのミドルウェア クラスの前にこれを挿入することをおすすめします。このミドルウェアより前に他のミドルウェアが起動される場合、そのミドルウェアがデータストアを呼び出すと、それが正しく処理されないためです。Django ミドルウェアの詳細をご確認ください。
次のステップ
以下の詳細を確認する。
- NDB でのエンティティの作成
- Datastore でトランザクションが処理される方法
- NDB クライアント ライブラリでクエリを作成してフォーマットする方法
- NDB および基盤 Memcache インフラストラクチャを使用したデータのキャッシュ
- Datastore に保存されたデータの管理