Python ゲストブックのコードのこの部分では、構造化データを Datastore に保存する方法を説明します。App Engine と Datastore では、データの分散、レプリケーション、ロード バランシングについて心配する必要はありません。単純な API で実現されます。加えて、強力なクエリエンジンとトランザクションも使用できます。
このページは複数ページからなるチュートリアルの一部です。設定などの手順を最初から見るには、ゲストブックの作成に移動してください。
送信されたメッセージの保存
データは、Datastore 内のエンティティと呼ばれるオブジェクトに書き込まれます。各エンティティには、それを一意に識別するキーが割り当てられます。エンティティでは、別のエンティティを「親」として指定することもできます。最初のエンティティは、親エンティティの「子」になります。こうして、データストア内のエンティティは、ファイル システムのディレクトリ構造と同じような階層構造空間を形成します。詳細については、強整合性に対応するデータ構造をご覧ください。
App Engine には Python 用のデータ モデリング API が付属しています。データ モデリング API を使用するために、サンプルアプリは google.appengine.ext.ndb
モジュールをインポートします。各メッセージには投稿者の名前、メッセージの内容、投稿日時が含まれています。アプリではメッセージが時系列で表示されます。次のコードは、データモデルを定義します。
このコードは、次の 3 つのプロパティで Greeting
モデルを定義します。値がメールアドレスと投稿者の ID を含む Author
オブジェクトである author
、値が文字列である content
、値が datetime.datetime
である date
です。
パラメータで詳細な動作を構成できるプロパティ コンストラクタもあります。ndb.StringProperty
コンストラクタに indexed=False
パラメータを渡すと、このプロパティの値にインデックスが付けられません。これにより、アプリでそのプロパティがクエリに使用されなくなるため、不要な書き込みをしなくて済みます。ndb.DateTimeProperty
コンストラクタに auto_now_add=True
パラメータを渡すと、アプリケーションで値が入力されない場合に、自動的に新しいオブジェクトに作成時の datetime
スタンプが付与されるようにモデルが構成されます。プロパティ タイプとそれらのオプションの完全なリストについては、NDB プロパティをご覧ください。
アプリケーションでは、新しい Greeting
オブジェクトを作成して Datastore に配置するためにデータモデルが使用されます。Guestbook
ハンドラが新しいメッセージを作成してそれらをデータストアに保存します。
この Guestbook
ハンドラは、新しい Greeting
オブジェクトを作成してから、その author
プロパティと content
プロパティをユーザーが投稿したデータに設定します。Greeting
の親は Guestbook
エンティティです。別のエンティティの親に設定する前に、Guestbook
エンティティを作成する必要はありません。この例では、トランザクションと整合性を目的としたプレースホルダとして親を使用します。詳細については、トランザクション ページをご覧ください。共通の祖先を共有するオブジェクトは、同じエンティティ グループに属しています。このコードでは date
プロパティが設定されないため、date
は自動的に auto_now_add=True
を使用して現在に設定されます。
最後に、greeting.put()
によって新しいオブジェクトがデータストアに保存されます。このオブジェクトをクエリから取得した場合は、put()
によって既存のオブジェクトが更新されます。このオブジェクトはモデル コンストラクタを使用して作成されているため、put()
によって新しいオブジェクトがデータストアに追加されます。
Datastore におけるクエリはエンティティ グループ内でのみ強整合性を示すため、コードでは、すべてのメッセージに共通する親を設定することにより、1 つのブック内のすべてのメッセージが同じエンティティ グループに割り当てられます。したがって、メッセージは常に書き込みの直後にユーザーに表示されます。ただし、同じエンティティ グループに書き込める頻度は毎秒 1 回に制限されます。実際のアプリケーションを設計するときは、この点を考慮する必要があります。Memcache などのサービスを使用すると、書き込み後に複数エンティティ グループを横断してクエリを実行した場合に、ユーザーに新しい結果が表示されなくなる可能性を低減できます。
送信されたメッセージの取得
Datastore は、データモデル用の高度なクエリエンジンを備えています。Datastore は従来型のリレーショナル データベースではないため、クエリを指定する際に SQL は使用しません。その代わりに、Datastore クエリを使用するか、GQL という SQL に似たクエリ言語を使用して、データのクエリを行います。Datastore のすべてのクエリ機能を活用するには、GQL によるクエリを使用することをおすすめします。
MainPage
ハンドラは、過去に送信されたメッセージを取得して表示します。greetings_query.fetch(10)
を呼び出すとクエリが実行されます。
Datastore インデックスの詳細
Datastore 内のすべてのクエリが 1 つ以上のインデックスから計算されます。このインデックスは、順序付けられたプロパティ値をエンティティ キーにマップするテーブルです。アプリケーションのデータストアの規模にかかわらず App Engine がすばやく結果を返すことができるのは、この仕組みによります。多くのクエリは組み込みのインデックスから計算できますが、より複雑なクエリの場合は、Datastore にカスタム インデックスが必要になります。カスタム インデックスを使用しない場合は、Datastore でこれらのクエリを効率的に実行できません。
たとえば、ゲストブック アプリケーションは、上位クエリと並べ替え順序を使用して、ゲストブックでフィルタリングし、日付順に並べ替えます。そのためには、アプリケーションの index.yaml
ファイルでカスタム インデックスを指定する必要があります。このファイルは、手動で編集することも、アプリケーションでローカルにクエリを実行することで自動的に処理することもできます。index.yaml
でインデックスを定義してから、アプリケーションをデプロイすると、カスタム インデックス情報もデプロイされます。
index.yaml
内のクエリの定義は次のようになります。
Datastore インデックスの詳細については、データストア インデックス ページをご覧ください。index.yaml
ファイルの正しい指定方法については、Python データストアのインデックスの構成をご覧ください。