エンティティの作成、取得、更新、削除

Datastore のデータ オブジェクトはエンティティと呼ばれ、個々のエンティティはクエリの目的で特定の種類に分類されます。たとえば、人事アプリケーションを作成する場合、各従業員を Employee という種類のエンティティで表すことができます。エンティティ データ値は、プロパティの形で表されます。エンティティの詳細については、祖先パストランザクションに関するドキュメントをご覧ください。

エンティティの作成とプロパティの設定

エンティティを作成して設定するには、そのモデルクラスのコンストラクタ メソッドを呼び出します。エンティティ モデルクラスの作成方法については、エンティティ モデルクラスの作成と使用をご覧ください。

次の例は、キーワード引数を使用してモデルクラス コンストラクタを呼び出す方法を示しています。

sandy = Account(
    username='Sandy', userid=123, email='sandy@example.com')

このコードは、プログラムのメインメモリでオブジェクトを作成します。ただし、プロセスが終了するとエンティティはなくなるため、次のように put() を呼び出してエンティティを Datastore に保持する必要があります。

sandy_key = sandy.put()

このコードは、後で Datastore からエンティティを取得するために使用できるキーを返します。

次のオプションのいずれかを使用してプロパティを設定します。

  • キーワード引数を使用してエンティティのプロパティをコンストラクタに指定します。
    sandy = Account(
        username='Sandy', userid=123, email='sandy@example.com')
  • エンティティの作成後にプロパティを手動で設定します。
    sandy = Account()
    sandy.username = 'Sandy'
    sandy.userid = 123
    sandy.email = 'sandy@example.com'
  • populate() という便宜的メソッドを使用して、1 回のオペレーションで複数のプロパティを設定します。
    sandy = Account()
    sandy.populate(
        username='Sandy',
        userid=123,
        email='sandy@gmail.com')

エンティティのプロパティをどの方法で設定する場合も、プロパティ タイプ(この場合は StringPropertyIntegerProperty)によってタイプチェックが行われます。

次に例を示します。

bad = Account(
    username='Sandy', userid='not integer')  # raises an exception
...
sandy.username = 42  # raises an exception

キーからエンティティを取得する

エンティティのキーがあれば、Datastore からエンティティを取得できます。

sandy = sandy_key.get()

キーメソッド kind()id() は、エンティティの種類と識別子をキーから復元します。

kind_string = sandy_key.kind()  # returns 'Account'
ident = sandy_key.id()  # returns '2'

エンティティのキーを使用して、URL への埋め込みに適したエンコード文字列を取得することもできます。

url_string = sandy_key.urlsafe()

これにより、agVoZWxsb3IPCxIHQWNjb3VudBiZiwIM のような結果が得られ、後でキーの再構築と元のエンティティの取得に使用できます。

sandy_key = ndb.Key(urlsafe=url_string)
sandy = sandy_key.get()

URL セーフ文字列は暗号のように見えますが、暗号化されているわけではないことに注意してください。簡単にデコードして、元のエンティティの種類と識別子を復元できます。

key = Key(urlsafe=url_string)
kind_string = key.kind()
ident = key.id()

このような URL セーフキーを使用する場合、メールアドレスなどの機密データはエンティティ識別子として使用しないでください。この解決策として、機密データのハッシュを識別子として使用する方法があります。このようにすると、暗号化されたキーを見ることのできる第三者がそれを利用してメールアドレスを収集することはできなくなります。ただし、第三者が既知のメールアドレスを使って自分でハッシュを生成し、そのアドレスが Datastore 内に存在するかどうかを確認することは可能ですので、ご注意ください。

エンティティの更新

既存のエンティティを更新するには、それを Datastore から取得し、そのプロパティを変更して元の場所に保管します。

sandy = key.get()
sandy.email = 'sandy@example.co.uk'
sandy.put()

この場合は、更新してもエンティティ キーは変更されないため、put() から返される値は無視できます。

エンティティの削除

エンティティが不要になると、キーの delete() メソッドを使用して Datastore から削除できます。

sandy.key.delete()

これはキーに対するオペレーションであり、エンティティ自体に対するオペレーションではないことに注意してください。常に None が返されます。

エンティティの一括削除

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

バッチ オペレーションの使用

エンティティまたはキーのまとまりを複数回の呼び出しではなく、たとえばループの内部で 1 回の呼び出しで処理できます。これにより、エンティティごとに別個のリモート プロシージャ コール(RPC)を呼び出すのではなく、一括処理用の RPC を 1 回呼び出すだけで処理することができます。

コード例を以下に示します。

list_of_keys = ndb.put_multi(list_of_entities)
list_of_entities = ndb.get_multi(list_of_keys)
ndb.delete_multi(list_of_keys)

上記のコードでは、キー オブジェクトのリストを ndb.get_multi に渡して、複数のエンティティを一括で取得します。ndb.get_multi は、エンティティ オブジェクトのリストを返します。Datastore に対応するエンティティがないキーの値は None になります。この方法でエンティティを取得すると、一括処理全体での Datastore への呼び出しが少なくなります(バッチあたりの呼び出しの数はバッチサイズ設定によって異なります)。