建立及使用實體金鑰

每個實體都會以應用程式資料儲存庫執行個體中專屬的鍵來識別,並包含下列項目:

  • 種類:種類通常是實體所屬模型類別的名稱,但您可以覆寫 classmethod _get_kind(),將其變更為其他字串。
  • 識別碼:您可以指定自己的「金鑰名稱」做為 ID,或是讓 Datastore 自動產生整數的數字 ID。

指定自訂金鑰名稱

以下範例會使用名為 id 的參數,隱含地建立具有字串 ID 的索引鍵:

account = Account(
    username='Sandy', userid=1234, email='[email protected]',
    id='[email protected]')

return account.key.id()  # returns '[email protected]'

您也可以直接設定金鑰名稱:

account.key = ndb.Key('Account', '[email protected]')

# You can also use the model class object itself, rather than its name,
# to specify the entity's kind:
account.key = ndb.Key(Account, '[email protected]')

讓 Datastore 產生 ID 以供金鑰使用

以下程式碼顯示如何使用自動產生的 ID 作為金鑰:

# note: no id kwarg
account = Account(username='Sandy', userid=1234, email='[email protected]')
account.put()
# account.key will now have a key of the form: ndb.Key(Account, 71321839)
# where the value 71321839 was generated by Datastore for us.

在金鑰中使用祖系路徑

從根實體開始,再從父項到子項,最後到指定實體的實體序列,即構成該實體的「祖系路徑」。實體、其父項、父項的父項等以此類推,全都是這個實體的「祖系」。Datastore 中的實體會形成階層式鍵值空間,類似於檔案系統的階層式目錄結構。

用於識別實體的完整金鑰,其中包含一系列指定其祖系路徑的種類-識別碼組合,並會以實體本身的種類-識別碼組合作結。類別 Key 的建構函式會接受這類類別和 ID 序列,並傳回代表對應實體的鍵物件。

以下範例說明瞭一個部落格服務,該服務會依修訂版本儲存訊息。訊息會依帳戶分類,修訂版本則會歸入訊息。

class Revision(ndb.Model):
    message_text = ndb.StringProperty()
...
ndb.Key('Account', '[email protected]', 'Message', 123, 'Revision', '1')
ndb.Key('Account', '[email protected]', 'Message', 123, 'Revision', '2')
ndb.Key('Account', '[email protected]', 'Message', 456, 'Revision', '1')
ndb.Key('Account', '[email protected]', 'Message', 789, 'Revision', '2')

在範例中,('Account', '[email protected]')('Message', 123)('Revision', '1') 都是類別-識別碼組合的例子。

請注意,Message 並非模型類別,只用於將修訂版本分組,而非儲存資料。

如程式碼範例所示,實體的種類是由清單中的「最後一個」種類/名稱組合指定:ndb.Key('Revision', '1')

使用命名參數

您可以使用已命名參數 parent,直接指定祖系路徑中的任何實體。以下所有標記法均代表相同金鑰:

ndb.Key('Account', '[email protected]', 'Message', 123, 'Revision', '1')

ndb.Key('Revision', '1', parent=ndb.Key(
    'Account', '[email protected]', 'Message', 123))

ndb.Key('Revision', '1', parent=ndb.Key(
    'Message', 123, parent=ndb.Key('Account', '[email protected]')))

指定根實體

根實體的祖系路徑空白,並且金鑰僅包含實體本身的種類與識別碼。

sandy_key = ndb.Key(Account, '[email protected]')

指定包含祖系的實體

如要以父項金鑰插入新訊息:

account_key = ndb.Key(Account, '[email protected]')

# Ask Datastore to allocate an ID.
new_id = ndb.Model.allocate_ids(size=1, parent=account_key)[0]

# Datastore returns us an integer ID that we can use to create the message
# key
message_key = ndb.Key('Message', new_id, parent=account_key)

# Now we can put the message into Datastore
initial_revision = Revision(
    message_text='Hello', id='1', parent=message_key)
initial_revision.put()

對於使用父項建立的鍵,parent() 方法會傳回代表父項實體的鍵:

message_key = initial_revision.key.parent()

使用數字金鑰 ID

您可以不指定 ID 建立實體,資料儲存庫會自動產生數字 ID。如果您選擇指定部分 ID,然後讓 Datastore 自動產生部分 ID,可能會違反不重複索引鍵的規定。為避免發生此情形,請保留特定範圍的數字來選擇 ID,或使用字串 ID 以便徹底杜絕此問題。

如要保留特定範圍的 ID,請使用模型類別的 allocate_ids() 類別方法進行下列操作:

  • 分配指定數量的 ID
  • 分配指定最大值以下的所有 ID。

分配 ID

如要為特定模型類別 MyModel 分配 100 個 ID:

first, last = MyModel.allocate_ids(100)

如要為父系金鑰 p 的實體分配 100 個 ID:

first, last = MyModel.allocate_ids(100, parent=p)

傳回的值 firstlast 是分配的第一個和最後一個 ID (含括在內)。您可以使用這些 ID 建構金鑰,如下所示:

keys = [ndb.Key(MyModel, id) for id in range(first, last+1)]

這些金鑰先前並未由資料儲存庫的內部 ID 產生器傳回,日後也不會在呼叫內部 ID 產生器時傳回。不過,allocate_ids() 方法不會檢查傳回的 ID 是否存在於資料儲存庫中,只會與 ID 產生器互動。

如要分配指定最大值以下的所有 ID:

first, last = MyModel.allocate_ids(max=N)

這可確保小於或等於 N 的所有 ID 都會視為已分配。傳回值 firstlast 會指出這項作業保留的 ID 範圍。嘗試保留已分配的 ID 並不構成錯誤;如果發生此情形,first 代表尚未分配的第一個 ID,而 last 則是最後一個分配的 ID。