從 DB 遷移至 NDB 用戶端程式庫

無需對 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 中,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 的簡介說明與參考資料。另外也可參閱 Khan Academy 實習生 Dylan Vassallo 探討如何將模組升級為 NDB 的部落格文章

Model 類別

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 解答以取得可能的解決方案。

Get

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)

Delete

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。如需更長的網址,請使用 ndb.TextProperty()


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)

不支援;一律允許字串以包含 \n


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 中,more 是指示游標位置是否有更多實體的 bool。


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)
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Python 2 適用的 App Engine 標準環境