2012-10-18 55 views
7

我想獲得一個知道實體ID和祖先的實體密鑰。 ID在祖先定義的實體組內是唯一的。 在我看來,使用ndb接口是不可能的。就我所瞭解的數據存儲而言,這可能是由於此操作需要完整的索引掃描才能執行。 我使用的解決方法是在模型中創建一個計算屬性,該屬性將包含密鑰的id部分。我現在能夠做一個祖先查詢並拿到鑰匙ndb通過沒有父母的ID檢索實體密鑰

class SomeModel(ndb.Model): 
    ID = ndb.ComputedProperty(lambda self: self.key.id()) 

    @classmethod 
    def id_to_key(cls, identifier, ancestor): 
     return cls.query(cls.ID == identifier, 
         ancestor = ancestor.key).get(keys_only = True) 

看來工作,但都沒有對這個問題沒有更好的辦法?

更新 看來,對於數據存儲中的自然的解決方案是使用完整路徑,而不是標識符。起初我認爲這太繁重了。在閱讀dragonx答案後,我重新設計了我的應用程序。令我驚奇的是,現在一切看起來都更簡單了。額外的好處是,我的實體將使用更少的空間,我不需要額外的索引。

+0

聽起來像是你答對了! –

+0

在實體組中不唯一保證ID - 僅限於給定的父實體。 –

回答

8

我也遇到過這個問題。我認爲你確實有解決方案。

更好的解決方案是停止使用ID來引用實體,並存儲實際密鑰或完整路徑。

在內部,我使用鍵而不是ID。

在我的rest API上,我曾用做http://url/kind/id(其中id看起來像「123」)來獲取實體。我修改它以提供實體的完整祖先路徑:http://url/kind/ancestor-ancestor-id(789-456-123),然後解析該字符串,生成一個密鑰,然後通過密鑰獲取。

+0

你說得對。完整的祖先路徑讓一切都變得簡單。看來這是在數據存儲中做這種事情的正確方法。謝謝 –

+0

不要忘記數據存儲中有一個「密鑰」類型,可用於存儲實際密鑰(KeyProperty)。 –

+0

在附註中,Java具有[這些方法](https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyFactory#keyToString%28com.google.appengine .api.datastore.Key%29)來序列化和反序列化鍵 – aimless

3

既然你對自己祖先的全部信息,你知道你的身份證,你可以直接創建一個鍵,得到了實體,具體如下:

my_key = ndb.Key(Ancestor, ancestor.key.id(), SomeModel, id) 
entity = my_key.get() 

這樣你避免作出查詢費用超過無論在金錢和速度方面都是如此。

希望這會有所幫助。

+1

這是一個很好的解決方案,如果祖先也是父母,但它不是我的情況 –

+0

既然你使用了「祖先」一詞,我以爲你的意思是說它是父母。如果情況並非如此,那麼我認爲你的方法是正確的。 –

1

我想對dargonx的答案做一點補充。

在我的前端應用程序,我用鑰匙的字符串表示:

str(instance.key()) 

當我需要做出一些改變與instence即使是後裔我使用它的鍵的唯一字符串表示。比如我有key_str - 參數從請求刪除實例「:

instance = Kind.get(key_str) 
instance.delete() 
0

我的解決方案是使用urlsafe不用擔心拿到的項目約父ID:

pk = ndb.Key(Product, 1234) 
usafe = LocationItem.get_by_id(5678, parent=pk).key.urlsafe() 
# now can get by urlsafe 
item = ndb.Key(urlsafe=usafe) 
print item 
相關問題