無需對 Datastore 進行任何變更
如果您想知道,儘管 API 不同,NDB 和舊版 ext.db 套件會寫入「完全」相同的資料到 Datastore。這代表您不用執行任何轉換到資料儲存庫的作業,而且只要使用相同的結構定義,就能輕鬆混合和比對 NDB 與 ext.db 程式碼。您甚至還可使用 ndb.Key.from_old_key() 和 key.to_old_key() 在 ext.db 和 NDB 索引鍵之間轉換。
一般差異
- NDB 有嚴格的類型要求。例如在 DB 中,如果需要的是索引鍵,您也可以傳送實體或字串。在 NDB 中,您就必須傳送索引鍵。 
- NDB 有嚴格的清單要求。例如在資料庫中, - db.put()會接收實體或實體清單。在 NDB 中,您可以使用- entity.put()放置單一實體,但使用- ndb.put_multi(<list>)放置實體清單。
- NDB 偏好方法而非函式。例如,NDB 使用 - key.get()和- entity.put(),而非- db.get(key)和- db.put(entity)。
- NDB 不喜歡提供兩個 API 來執行相同的工作 (另一方面,NDB 有時會提供兩個 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。如需更長的網址,請使用  | 
| 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) |