エンティティ、プロパティ、キー

注: 新しいアプリケーションを作成する際には、NDB クライアント ライブラリの使用を強くおすすめします。NDB クライアント ライブラリには、Memcache API によるエンティティの自動キャッシュなど、DB クライアント ライブラリにはないメリットがいくつかあります。古い DB クライアント ライブラリを使用している場合は、DB から NDB への移行ガイドをお読みください。

Cloud Datastore のデータ オブジェクトはエンティティと呼ばれます。エンティティには 1 つ以上の名前付きプロパティがあり、各プロパティに 1 つ以上の値を設定できます。同じ種類のエンティティが同じプロパティを持つとは限りません。また、エンティティの特定のプロパティの値がすべて同じデータ型である必要はありません(必要に応じて、アプリケーション独自のデータモデルでこのような制限を確立して強制できます)。

Cloud Datastore はさまざまなデータ型のプロパティ値をサポートしています。たとえば、次のようなものがあります。

  • 整数
  • 浮動小数点数
  • 文字列
  • 日付
  • バイナリデータ

すべての型の一覧は、プロパティと値の型をご覧ください。

Cloud Datastore 内の各エンティティはキーによって一意に識別されます。キーは次のコンポーネントで構成されています。

  • エンティティの名前空間マルチテナンシーを可能にします。
  • エンティティの種類。Cloud Datastore のクエリ用にエンティティを分類します。
  • 個々のエンティティの識別子。次のいずれかになります。
    • キー名の文字列
    • 整数の数値 ID
  • オプションの祖先パス。Cloud Datastore 階層内でのエンティティの位置を指定します。

アプリケーションではエンティティのキーを使用して Cloud Datastore から個々のエンティティをフェッチできます。また、エンティティのキーやプロパティ値に基づくクエリを実行して 1 つ以上のエンティティを取得することもできます。

Python App Engine SDK には、データ モデリング ライブラリが含まれています。このライブラリを使用して、Cloud Datastore エンティティを Python クラスのインスタンスとして表したり、これらのインスタンスをデータストアに格納して取得することができます。

Cloud Datastore 自体がエンティティの構造になんらかの制限(特定のプロパティは特定の型の値を持たなければならないなど)を課すことはありません。この役割はアプリケーションとデータ モデリング ライブラリが担います。

種類と識別子

Cloud Datastore の各エンティティは特定の種類に属しています。種類とは、クエリ用にエンティティを分類するカテゴリのことです。たとえば、人事アプリケーションでは、会社の各従業員が Employee という種類のエンティティで表されます。Python Datastore API では、エンティティの種類はモデルクラスによって決まります。モデルクラスは、アプリケーション内でデータ モデリング ライブラリ クラスの db.Model のサブクラスとして定義します。モデルクラスの名前が、そのエンティティの属する種類となります。2 つのアンダースコア(__)で始まる種類名はすべて予約済みであり、使用できません。

次の例では、種類が Employee であるエンティティを作成し、プロパティ値を設定した後、データストアに保存します。

import datetime
from google.appengine.ext import db

class Employee(db.Model):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  hire_date = db.DateProperty()
  attended_hr_training = db.BooleanProperty()

employee = Employee(first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

Employee クラスは、データモデルに first_namelast_namehire_dateattended_hr_training の 4 つのプロパティを宣言します。Model スーパークラスにより、Employee オブジェクトの属性がこのモデルに準拠することが確実になります。たとえば、hire_date 属性に文字列値を割り当てようとするとランタイム エラーになります。これは、hire_date のデータモデルが db.DateProperty として宣言されているためです。

種類に加え、各エンティティは作成時に割り当てられた識別子を持ちます。識別子はエンティティのキーの一部であるため、エンティティに永続的に割り当てられており、変更できません。識別子を割り当てる方法は 2 通りあります。

  • アプリケーションからエンティティの固有のキー名文字列を指定する。
  • エンティティに整数の数値 ID が自動的に割り当てられるように Cloud Datastore を設定する。

エンティティにキー名を割り当てるには、次のように、エンティティの作成時にモデルクラスのコンストラクタに対して名前付き引数 key_name を指定します。

# Create an entity with the key Employee:'asalieri'.
employee = Employee(key_name='asalieri')

Cloud Datastore で数値 ID を自動的に割り当てるには、key_name 引数を省略します。

# Create an entity with a key such as Employee:8261.
employee = Employee()

識別子の割り当て

Cloud Datastore は、次の 2 種類の自動 ID ポリシーを使用して自動 ID を生成するように構成できます。

  • default ポリシーは、未使用の ID をランダムに生成します。この ID はほぼ均等に分布しています。各 ID は最大 16 桁の 10 進数になります。
  • legacy ポリシーは、連続していない小さい整数の ID を生成します。

エンティティの ID をユーザーに表示する場合や、ID の順序に従ってなんらかの処理を行う場合は、手動で割り当てることをおすすめします。

Cloud Datastore は、おおむね均一に分散した一連の未使用 ID をランダムに生成します。各 ID は最大 16 桁の 10 進数になります。

システムから割り当てられる ID 値はエンティティ グループに対して一意であることが保証されています。あるエンティティ グループまたは名前空間から別のエンティティ グループまたは名前空間にエンティティをコピーしキーの ID 部分を保持する場合は、まず ID を割り当ててその ID が Cloud Datastore による今後の割り当てで選ばれないようにしてください。

祖先パス

Cloud Datastore 内の各エンティティは、ファイル システムのディレクトリ構造と同様の階層的に構造化された空間を形成します。エンティティを作成するときに、別のエンティティを親として設定することもできます。新しいエンティティは、この親エンティティの子になります(ファイル システムとは異なり、親エンティティが実際に存在している必要はありません)。親を持たないエンティティは、ルート エンティティとなります。 エンティティと親との割り当ては永続的であり、エンティティの作成後は変更できません。同じ親を持つ 2 つのエンティティ、または 2 つのルート エンティティ(親を持たないエンティティ)に同じ数値 ID が割り当てられることはありません。

エンティティの親、親の親、さらにその親などは順に祖先として位置付けられ、エンティティの子、子の子、さらにその子などは順に子孫として位置付けられます。 ルート エンティティとその子孫のエンティティは、すべて同じエンティティ グループに属します。 ルート エンティティから始まり、親から子を経由して対象のエンティティに至るまでの連なりを、エンティティの祖先パスといいます。 エンティティを識別する完全なキーは、エンティティの祖先パスから始まってそのエンティティ自身で終わる一連の「種類と識別子のペア」で構成されます。

[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]

ルート エンティティの場合は祖先パスが空で、エンティティ自身の種類と識別子だけでキーが構成されています。

[Person:GreatGrandpa]

この概念を次の図に示します。

エンティティ グループ内のルート エンティティと子エンティティの関係を示す図

エンティティの親を指定するには、子エンティティの作成時にモデルクラスのコンストラクタに対して parent 引数を使用します。この引数の値には、親エンティティ自体またはそのキーを指定できます。指定するキーを取得するには、親エンティティの key() メソッドを呼び出します。次の例は、種類が Address のエンティティを作成し、Employee エンティティをその親として指定する 2 つの方法を示しています。

# Create Employee entity
employee = Employee()
employee.put()

# Set Employee as Address entity's parent directly...
address = Address(parent=employee)

# ...or using its key
e_key = employee.key()
address = Address(parent=e_key)

# Save Address entity to datastore
address.put()

トランザクションとエンティティ グループ

エンティティの作成、更新、削除は、すべてトランザクションのコンテキストで行われます。1 つのトランザクションで、このようなオペレーションが複数実行される場合もあります。トランザクションでは、データの整合性を維持するため、すべてのオペレーションを 1 つの単位として Cloud Datastore に適用します。いずれかのオペレーションが失敗した場合、すべてのオペレーションが適用されません。また同一のトランザクション内で実行されるすべての強整合性読み取り(祖先クエリまたは取得)は、データの一貫性のあるスナップショットを維持します。

上記のとおり、エンティティ グループとは、祖先から共通のルート要素までが連結された一連のエンティティです。データをエンティティ グループに編成する場合、実行可能なトランザクションの種類が制限されることがあります。

  • トランザクションがアクセスするすべてのデータは、最大 25 のエンティティ グループに制限されます。
  • トランザクション内でクエリを使用する場合は、適切なデータと一致する祖先フィルタを指定できるように、データをエンティティ グループに編成する必要があります。
  • 1 つのエンティティ グループに対し、1 秒につき約 1 つのトランザクションという書き込みスループットの制限があります。これは高い信頼性とフォールト トレランスを実現するため、Cloud Datastore が広範な地域にわたって個々のエンティティ グループをマスターなしで同期複製するために生じる制限です。

多くのアプリケーションでは、相互に関連性のないデータに対する広範なビューを取得するのであれば、結果整合性(複数のエンティティ グループに対する非祖先クエリ、多少古いデータが返される場合もある)の使用で対応できます。一方、関連性の高いデータから成る単一データセットを表示または編集する場合は、強整合性の使用が適します(祖先クエリ、または単一エンティティに対する get)。このようなアプリケーションでは通常、関連性の高い個々のデータセットに対し、個別のエンティティ グループを作成すると効率的です。詳細については、強整合性に対応するデータ構造をご覧ください。

プロパティと値の型

エンティティに関連付けられたデータ値は 1 つ以上のプロパティで構成されます。 各プロパティには名前と 1 つ以上の値があります。プロパティは複数の型の値を持つことができるため、2 つのエンティティがあった場合、プロパティが同じであっても型が異なる値が存在する場合があります。プロパティにはインデックスを付けることも付けないでおくこともできます(プロパティ P で並べ替えまたはフィルタリングを行うクエリは、P にインデックスが付けられていないエンティティを無視します)。1 つのエンティティに、インデックスが付けられたプロパティを最大 20,000 個まで割り当てることができます。

サポートされている値の型は、次のとおりです。

値の型 Python の型 並べ替え順
整数 int
long
数値 64 ビット整数(符号付き)
浮動小数点数 float 数値 64 ビット倍精度、
IEEE 754
ブール値 bool False<True
テキスト文字列(短い) str
unicode
Unicode
(ASCII テキストとして処理された str
最大 1,500 バイト
テキスト文字列(長い) db.Text なし 最大 1 メガバイト

インデックス未登録
バイト文字列(短) db.ByteString バイト順 最大 1,500 バイト
バイト文字列(長い) db.Blob なし 最大 1 メガバイト

インデックス未登録
日時 datetime.date
datetime.time
datetime.datetime
時系列
地理的座標 db.GeoPt 最初に緯度、
次に経度
住所 db.PostalAddress Unicode
電話番号 db.PhoneNumber Unicode
メールアドレス db.Email Unicode
Google アカウント ユーザー users.User メールアドレス
Unicode 順
インスタント メッセージング ハンドル db.IM Unicode
リンク db.Link Unicode
カテゴリ db.Category Unicode
評価 db.Rating 数値
Cloud Datastore のキー db.Key パス要素順
(種類、識別子、
種類、識別子...)
Blobstore のキー blobstore.BlobKey バイト順
Null NoneType なし

重要: UserProperty にはメールアドレスとユーザーの一意の ID が含まれているため、これを保存しないことを強くおすすめします。ユーザーが自分のメールアドレスを変更すると、そのユーザーの古い保存済みの User と新しい User の値を比較したときに一致しなくなります。

テキスト文字列とエンコードされていないバイナリデータ(バイト文字列)については、Cloud Datastore は、次の 2 つの値の型をサポートします。

  • 短い文字列(最大 1,500 バイト)は、インデックスに登録され、クエリのフィルタ条件や並べ替えの順序付けに使用できます。
  • 長い文字列(最大 1 メガバイト)は、インデックスに登録されず、クエリのフィルタや並べ替えの順序付けには使用できません。
注: 長いバイト文字列型は、Cloud Datastore API では Blob と呼ばれています。この型は、Blobstore API で使用される blob とは関係ありません。

型が混合した値を持つプロパティをクエリで扱う場合、内部表現に基づく決定論的な順序付けが使用されます。

  1. Null 値
  2. 固定小数点数
    • 整数
    • 日時型
    • 評価
  3. ブール値
  4. バイト列
    • バイト文字列
    • Unicode 文字列
    • Blobstore のキー
  5. 浮動小数点数
  6. 地理的座標
  7. Google アカウントのユーザー
  8. Cloud Datastore のキー

長いテキスト文字列と長いバイト文字列はインデックスに登録されないため、順序付けは定義されていません。

エンティティの操作

アプリケーションは Cloud Datastore API を使用してエンティティを作成、取得、更新、削除できます。エンティティの完全なキーがわかっている場合(または親のキー、種類、識別子からキーを導出できる場合)、アプリケーションはそのキーを使用してエンティティを直接操作できます。また、Cloud Datastore クエリの結果としてエンティティのキーを取得することもできます。詳細については、データストアのクエリをご覧ください。

エンティティの作成

Python で新しいエンティティを作成するには、モデルクラスのインスタンスを作成し、必要に応じてプロパティを設定したうえで、そのインスタンスの put() メソッドを呼び出してエンティティをデータストアに保存します。エンティティのキー名は、コンストラクタに key_name 引数を渡すことによって指定できます。

employee = Employee(key_name='asalieri',
                    first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

キー名を指定しない場合は、Cloud Datastore によって数値 ID がエンティティのキーとして自動的に生成されます。

employee = Employee(first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

エンティティの取得

指定したキーで識別されるエンティティを取得するには、Key オブジェクトを引数として db.get() 関数に渡します。Key オブジェクトはクラスメソッド Key.from_path() を使用して生成できます。完全なパスは、祖先パスの一連のエンティティで構成されます。各エンティティは、種類(文字列)とそれに続く識別子(キー名または数値 ID)で表されます。

address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
address = db.get(address_k)

db.get() は該当するモデルクラスのインスタンスを返します。必ず、取得するエンティティのモデルクラスをインポートしておいてください。

エンティティの更新

既存のエンティティを更新するには、オブジェクトの属性を変更してから、そのオブジェクトの put() メソッドを呼び出します。そのオブジェクト データで既存のエンティティが上書きされます。put() を呼び出すたびにオブジェクト全体が Cloud Datastore に送信されます。

プロパティを削除するには、Python オブジェクトから属性を削除します。

del address.postal_code

その後、オブジェクトを保存します。

エンティティの削除

エンティティを削除するには、エンティティのキーを指定して db.delete() 関数を呼び出します。

address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
db.delete(address_k)

または、エンティティ固有の delete() メソッドを呼び出します。

employee_k = db.Key.from_path('Employee', 'asalieri')
employee = db.get(employee_k)

# ...

employee.delete()

一括オペレーション

db.put()db.get()db.delete() 関数(およびそれぞれの非同期バージョンである db.put_async()db.get_async()db.delete_async())にはリスト引数を指定できるため、1 回の Cloud Datastore 呼び出しで複数のエンティティを操作できます。

# A batch put.
db.put([e1, e2, e3])

# A batch get.
entities = db.get([k1, k2, k3])

# A batch delete.
db.delete([k1, k2, k3])

一括オペレーションを実行してもコストは変わりません。キーが存在するかどうかにかかわらず、一括オペレーションに含まれるすべてのキーについて課金されます。オペレーションに含まれるエンティティのサイズは、コストに影響しません。

エンティティの一括削除

多数のエンティティを削除する必要がある場合は、Cloud Dataflow を使用してエンティティを一括削除することをおすすめします。

空のリストの使用

NDB インターフェースでは、Cloud Datastore はこれまで静的なプロパティと動的なプロパティのどちらについても空のリストを省略されたプロパティとして書き込んでいました。下位互換性を維持するため、この動作は引き続きデフォルトになっています。この動作をグローバルに、または ListProperty ごとにオーバーライドするには、Property クラスで write_empty_list 引数を true に設定します。これで、空のリストが Cloud Datastore に書き込まれ、空のリストとして読み取れるようになります。

DB インターフェースでは、これまでプロパティが動的な場合は空のリストの書き込みがまったく許可されていませんでした。空のリストを書き込もうとすると、エラーが発生しました。つまり、DB の動的なプロパティについては、下位互換性のために保持する必要があるデフォルトの動作がないため、動的なモデルでは変更なしで空のリストを読み書きできます。

しかし、DB の静的なプロパティについては、空のリストが省略されたプロパティとして書き込まれていたため、下位互換性を維持するためこの動作がデフォルトで継続されます。DB の静的なプロパティで空のリストを有効にするには、Property クラスで write_empty_list 引数を true に設定します。これで、空のリストが Cloud Datastore に書き込まれるようになります。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Python 2 の App Engine スタンダード環境