Datastore の変更は不要
異なる API にも関わらず、NDB と古い ext.db パッケージがまったく同じデータをデータストアに書き込むのは不思議に感じるかもしれません。スキーマが同じであれば、データベースの変換を行う必要はなく、NDB と ext.db コードを混在させることができます。また、ndb.Key.from_old_key() と key.to_old_key() を使用して、ext.db キーと NDB キーの間で変換を行うこともできます。
全般的な違い
NDB はタイプの扱いが厳密です。db では、キーが必要な場合、エンティティまたは文字列を渡すことができます。NDB ではキーを渡す必要があります。
NDB はリストの扱いが厳密です。たとえば、db では、
db.put()
はエンティティまたはエンティティのリストを受け取ります。NDB では、entity.put()
を使用して単一のエンティティを配置しますが、エンティティのリストはndb.put_multi(<list>)
を使用して配置します。NDB は関数よりもメソッドを使用します。たとえば、NDB では、
db.get(key)
やdb.put(entity)
ではなくkey.get()
とentity.put()
を使用します。NDB では、同じ処理の実行に 2 つの API を提供しません。処理が少しでも異なれば、2 つの API を提供する場合もあります。
API 呼び出しの比較
以下の表では、ndb と古い ext.db モジュールの類似点と相違点を示します。NDB の説明とリファレンスについては、NDB の公式ドキュメントをご覧ください。
モデルクラス
google.appengine.ext.db | ndb.model |
class MyModel(db.Model): foo = db.StringProperty() |
class MyModel(ndb.Model): foo = ndb.StringProperty() |
@classmethod def kind(cls): return 'Foo' |
@classmethod def _get_kind(cls): return 'Foo' |
MyModel.kind() |
MyModel._get_kind() |
MyModel.properties() model_instance.properties() |
MyModel._properties # No () !! model_entity._properties |
MyExpando.dynamic_properties() |
MyExpando._properties # No () !! |
エンティティ
google.appengine.ext.db | ndb.model |
MyModel(key_name='my_key') |
MyModel(id='my_key') |
MyModel(key_name='my_key', parent=model_instance) |
MyModel(id='my_key', parent=model_instance.key) |
key = model_instance.key() |
key = model_instance.key # No () !! |
model_instance = MyModel( foo='foo', bar='bar', baz='baz') |
model_instance = MyModel( foo='foo', bar='bar', baz='baz') |
model_instance.foo = 'foo' model_instance.bar = 'bar' model_instance.baz = 'baz' |
model_instance.foo = 'foo' model_instance.bar = 'bar' model_instance.baz = 'baz' # or a shortcut... model_instance.populate( foo='foo', bar='bar', baz='baz') |
model_instance.is_saved() |
同等のものはありません。可能な解決策については、Stack Overflow をご覧ください。 |
取得
google.appengine.ext.db | ndb.model |
MyModel.get_by_key_name('my_key') |
MyModel.get_by_id('my_key') |
MyModel.get_by_id(42) |
MyModel.get_by_id(42) |
db.get(key) |
key.get() |
MyModel.get(key) |
key.get() |
db.get(model_instance) |
model_instance.key.get() |
db.get(list_of_keys) |
ndb.get_multi(list_of_keys) |
db.get(list_of_instances) |
ndb.get_multi([x.key for x in list_of_instances]) |
MyModel.get_or_insert('my_key', parent=model_instance, foo='bar') |
MyModel.get_or_insert('my_key', parent=model_instance.key, foo='bar') |
put
google.appengine.ext.db | ndb.model |
db.put(model_instance) |
model_instance.put() |
db.put(list_of_model_instances) |
ndb.put_multi( list_of_model_instances) |
削除
google.appengine.ext.db | ndb.model |
model_instance.delete() |
model_instance.key.delete() |
db.delete(model_instance) |
model_instance.key.delete() |
db.delete(key) |
key.delete() |
db.delete(list_of_model_instances) |
ndb.delete_multi([m.key for m in list_of_model_instances]) |
db.delete(list_of_keys) |
ndb.delete_multi(list_of_keys) |
プロパティ
google.appengine.ext.db | ndb.model |
db.BlobProperty() |
ndb.BlobProperty() |
db.BooleanProperty() |
ndb.BooleanProperty() |
db.ByteStringProperty() |
ndb.BlobProperty(indexed=True) |
db.CategoryProperty() |
ndb.StringProperty() |
db.DateProperty() |
ndb.DateProperty() |
db.DateTimeProperty() |
ndb.DateTimeProperty() |
db.EmailProperty() |
ndb.StringProperty() |
db.FloatProperty() |
ndb.FloatProperty() |
db.GeoPtProperty() |
ndb.GeoPtProperty() |
db.IMProperty() |
同等のものはありません。 |
db.IntegerProperty() |
ndb.IntegerProperty() |
db.LinkProperty() |
ndb.StringProperty() 最大サイズは 500 です。これより長い URL の場合には |
db.ListProperty(bool) db.ListProperty(float) db.ListProperty(int) db.ListProperty(db.Key) # etc. |
ndb.BooleanProperty(repeated=True) ndb.FloatProperty(repeated=True) ndb.IntegerProperty(repeated=True) ndb.KeyProperty(repeated=True) # etc. |
db.PhoneNumberProperty() |
ndb.StringProperty() |
db.PostalAddressProperty() |
ndb.StringProperty() |
db.RatingProperty() |
ndb.IntegerProperty() |
db.ReferenceProperty(AnotherModel) model_instance.prop MyModel.prop \ .get_value_for_datastore \ (model_instance) |
ndb.KeyProperty(kind=AnotherModel) model_instance.prop.get() model_instance.prop |
# Using the backreference set other = model_instance.prop other.prop_set.fetch(N) |
# No direct equivalent; emulation: other = model_instance.prop.get() MyModel.query( MyModel.prop == other.key).fetch(N) |
db.SelfReferenceProperty() |
ndb.KeyProperty(kind='ThisModelClass') |
db.StringProperty() |
ndb.StringProperty() |
db.StringProperty(multiline=True) |
サポートされていません。文字列には |
db.StringListProperty() |
ndb.StringProperty(repeated=True) |
db.TextProperty() |
ndb.TextProperty() |
db.TimeProperty() |
ndb.TimeProperty() |
db.UserProperty() |
ndb.UserProperty() |
blobstore.BlobReferenceProperty() |
ndb.BlobKeyProperty() |
キーの作成
google.appengine.ext.db | ndb.model |
key = db.Key(encoded_key) |
key = ndb.Key(urlsafe=encoded_key) |
key = db.Key.from_path( 'MyKind', 'some_id', 'MyKind', 'some_id') |
key = ndb.Key( 'MyKind', 'some_id', 'MyKind', 'some_id') |
key = db.Key.from_path( MyModel, 'some_id', parent=model_instance, namespace='my_namespace') |
key = ndb.Key( MyModel, 'some_id', parent=model_instance.key, namespace='my_namespace') |
キー操作
google.appengine.ext.db | ndb.model |
key.id_or_name() |
key.id() |
key.id() |
key.integer_id() |
key.name() |
key.string_id() |
key.has_id_or_name() |
key.id() is None # or... model_instance.has_complete_key() |
key.app(), key.namespace(), key.parent(), key.kind() |
同じです。 |
str(key) |
key.urlsafe() |
key.to_path() |
key.flat() |
db.allocate_ids(MyModel, size) |
S, E = MyModel.allocate_ids(size) |
db.allocate_id_range(MyModel,X,Y) |
S, E = MyModel.allocate_ids(max=Y) assert S <= X |
トランザクション
google.appengine.ext.db | ndb.model |
db.run_in_transaction(function) |
ndb.transaction(function) |
db.run_in_transaction( function, *args, **kwds) |
ndb.transaction( lambda: function(*args, **kwds)) |
db.run_in_transaction_custom_retries(n, function) |
ndb.transaction(function, retries=n) |
opts = \ db.create_transaction_options(xg=True) db.run_in_transaction_options(opts, fun) |
ndb.transaction(fun, xg=True) |
クエリ
google.appengine.ext.db | ndb.model |
q = MyModel.all() |
q = MyModel.query() |
for result in q.run(): ... |
for result in q.iter(): ... |
q = MyModel.all() \ .filter('foo =', 'bar') \ .filter('baz >=', 'ding') |
q = MyModel.query( MyModel.foo == 'bar', MyModel.baz >= 'ding') |
q = MyModel.all() q.filter('foo =', 'bar') q.filter('baz >=', 'ding') q.order('-foo') results = q.fetch(10) |
q = MyModel.query() q = q.filter(MyModel.foo == 'bar') q = q.filter(MyModel.baz >= 'ding') q = q.order(-MyModel.foo) results = q.fetch(10) |
q.filter('__key__', k) # k is a db.Key instance |
q = q.filter(MyModel._key == k) # k is an ndb.Key instance |
a.filter('__key__ >=', k) # k is a db.Key instance |
q = q.filter(MyModel._key >= k) # k is an ndb.Key instance |
class MyExpando(Expando): pass q = MyExpando.all() q.filter('foo =', 'bar') |
class MyExpando(Expando): pass q = MyExpando.query( ndb.GenericProperty('foo') == 'bar') |
class Foo(Model): ... class Bar(Model): foo = ReferenceProperty(Foo) myfoo = <some Foo instance> for bar in myfoo.bar_set(): ... |
class Foo(Model): ... class Bar(Model): foo = KeyProperty(kind=Foo) myfoo = <some Foo instance> for bar in \ Bar.query(Bar.foo == myfoo.key): ... |
q = MyModel.all() q.ancestor(ancestor_key) |
q = MyModel.query(ancestor=ancestor_key) |
q = MyModel.all(keys_only=True) r = q.fetch(N) |
r = MyModel.query() \ .fetch(N, keys_only=True) # Alternatively: q = MyModel.query( default_options=QueryOptions( keys_only=True)) r = q.fetch(N) |
q = MyModel.gql(...) |
# same thing |
カーソル
q = MyModel.all() a = q.fetch(20) cur = q.cursor() |
q = MyModel.query() a, cur, more = q.fetch_page(20) NDB では、 |
q.with_cursor(cur) b = q.fetch(20) |
b, cur, more = \ q.fetch_page(20, start_cursor=cur) |
q.with_cursor(end_cursor=cur) b = q.fetch(20) |
q.fetch(20, end_cursor=cur) |