エンティティ用のモデルクラスを作成する必要があります。作成する方法は次の 2 つです。
- エンティティ プロパティを定義するモデルクラスを作成する
- 事前にエンティティを定義しない expando モデルクラスを作成する
このドキュメントでは、それぞれの種類のモデルクラスを作成する方法について説明します。また、アプリケーションが、それぞれの get()
の前など、特定の種類のオペレーションの前または後に特定のコードを実行できるように、モデルフックを作成する方法についても説明します。
プロパティを使用したモデルクラスの作成
エンティティを作成する前に、1 つまたは複数のエンティティ プロパティを定義するモデルクラスを作成する必要があります。次に例を示します。
...
それぞれの Account エンティティにユーザー名、ユーザー ID、メールのプロパティを含めます。
プロパティの型の完全なリストについては、エンティティ プロパティ リファレンスをご覧ください。
Expando モデルクラスの作成
事前にプロパティを定義するモデルクラスを必ずしも使用する必要はありません。Expando
という特殊なモデル サブクラスを使用すると、エンティティの動作が変化し、割り当てられたすべての属性がデータストアに保存されます。なお、このような属性をアンダースコアで始めることはできません。
次に Expando モデルの作成方法を示します。
...
これにより、整数値 1
を持つ foo
プロパティ、文字列値 'blah'
の bar
プロパティ、さらに文字列値 'exp'
、'and'
、'oh'
の反復プロパティ tag
を含むエンティティがデータストアに書き込まれます。プロパティにはインデックスが付き、エンティティの _properties
属性を使って照会できます。
データストアから値を取得することで作成される Expando
には、データストアに保存されたすべてのプロパティ値に関するプロパティが含まれます。
アプリケーションは、事前定義されたプロパティを Expando
サブクラスに次のように追加できます。
...
これにより、employee
に対して、値が 'Sandy'
の name
属性、値が None
の age
属性、値が 'SF'
の動的属性 location
が付与されます。
プロパティがインデックス化されていない Expando
サブクラスを作成するには、サブクラス定義で _default_indexed = False
を設定します。
...
Expando
エンティティで _default_indexed
を設定することもできます。この場合、設定後に割り当てられるすべてのプロパティに影響が及びます。
他の便利な手法として、Expando
という種類に対して動的プロパティをクエリできます。次のようなクエリがあるとします。
これは機能しません。location プロパティ用のプロパティ オブジェクトがクラスに存在しないためです。代わりに GenericProperty
を使用し、動的プロパティ用にクラス Expando
で次のように使用します。
モデルフックの使用
NDB には、シンプルなフック メカニズムが用意されています。フックを定義すると、アプリケーションは特定の種類のオペレーションの前または後に特定のコードを実行できます。たとえば、Model
でそれぞれの get()
の前にいずれかの関数を実行できます。
フック関数は、該当するメソッドの同期バージョン、非同期バージョン、マルチ バージョンを使用する際に実行されます。たとえば「get 前(プリ get)」フックは get()
、get_async()
、get_multi()
のすべてに適用されます。それぞれのフックには RPC 前(プリ RPC)および RPC 後(ポスト RPC)バージョンがあります。
フックは次の場合に役立つ可能性があります。
- クエリをキャッシュする
- ユーザーごとの Cloud Datastore アクティビティを監査する
- データベース トリガーを模倣する
次の例は、フック関数を定義する方法を示しています。
...
...
非同期 API でポストフックを使用する場合、check_result()
、get_result()
を呼び出すか、(タスクレット内で)非同期メソッドの future を生成することで、フックがトリガーされます。ポストフックは、RPC が成功したかどうかを検査しません。失敗した場合でも、フックは実行されます。
すべてのポストフックには、呼び出し署名の末尾に Future 引数があります。この Future
オブジェクトは、アクションの結果を保持します。この Future
に対して get_result()
を呼び出すことで、結果を取得できます。フックが呼び出される時点までには Future
が完了しているため、get_result()
は決してブロックしません。
プリフック中に例外が発生すると、リクエストが発生しなくなります。フックは <var>*</var>_async
メソッド内でトリガーされますが、プリ RPC フックで tasklets.Return
を起動して RPC をプリエンプトすることはできません。