2012-08-27 71 views
2

在GAE文檔,它指出:在Google App Engine的for循環中查詢的有效方法?

因爲每個得到()或放()操作調用單獨的遙控 過程調用(RPC),發出許多這樣的呼叫內的環是 低效的方式來一次處理一組實體或密鑰。

誰知道我在代碼中有多少其他的低效率,所以我想盡量減少。目前,我確實有一個for循環,每個迭代都有一個單獨的查詢。假設我有一個用戶,並且一個用戶有朋友。我想獲取用戶的每個朋友的最新更新。所以,我有什麼是該用戶的朋友的數組:

for friend_dic in friends: 
     email = friend_dic['email'] 
     lastUpdated = friend_dic['lastUpdated'] 
     userKey = Key('User', email) 
     query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated) 
     qit = query.iter() 
     while (yield qit.has_next_async()): 
      status = qit.next() 
      status_list.append(status.to_dict()) 
raise ndb.Return(status_list) 

有沒有一種更有效的方式來做到這一點,可能在某種程度上批次所有這些到一個單一的查詢?

+0

你能提供你的數據模型嗎?取決於你如何存儲朋友關係,可能會有一個優化。 「朋友」只是一個ListProperty(或者如果您使用NDB時是重複屬性),還是您爲「朋友」關係查詢單獨的模型? – someone1

+0

沒有朋友只是一個列表屬性。那麼有一個單獨的模型爲朋友,但這些不保存lastUpdated,所以我只是從客戶端設備的朋友,以及他們上次更新的日期,並把它們放在一本字典中。 – Snowman

+0

您能否提供代碼對於你如何獲得「朋友」,你是什麼意思,你從客戶端設備獲得朋友? – someone1

回答

4

試着看一下NDB的地圖功能:https://developers.google.com/appengine/docs/python/ndb/queryclass#Query_map_async

實例(假設你把你的朋友的關係在一個單獨的模型中,這個例子中,我假設Relationships模型):

@ndb.tasklet 
def callback(entity): 
    email = friend_dic['email'] 
    lastUpdated = friend_dic['lastUpdated'] 
    userKey = Key('User', email) 
    query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated) 
    status_updates = yield query.fetch_async() 
    raise ndb.Return(status_updates) 

qry = ndb.gql("SELECT * FROM Relationships WHERE friend_to = :1", user.key) 
updates = yield qry.map_async(callback) 
#updates will now be a list of status updates 

更新:

加深對您的數據模型的理解:

queries = [] 
status_list = [] 
for friend_dic in friends: 
    email = friend_dic['email'] 
    lastUpdated = friend_dic['lastUpdated'] 
    userKey = Key('User', email) 
    queries.append(ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated).fetch_async()) 

for query in queries: 
    statuses = yield query 
    status_list.extend([x.to_dict() for x in statuses]) 

raise ndb.Return(status_list) 
+0

我喜歡這個...... Future對象在哪裏?假設我想運行查詢,然後執行其他操作。調用更新= ...等待所有結果都被提取?我如何開始查詢,但做其他的事情,並稍後返回結果? – Snowman

+0

實際上等待......兩個單獨的查詢有什麼意義?我已經在字典中擁有該用戶的朋友,爲什麼再次查詢它們? – Snowman

+0

看看我的編輯過的代碼......這就是我現在正在做的事情......它可以得到比我所做的更多的異步嗎? – Snowman

1

你可以同時使用NDB異步方法執行這些查詢:

from google.appengine.ext import ndb 

class Bar(ndb.Model): 
    pass 

class Foo(ndb.Model): 
    pass 

bars = ndb.put_multi([Bar() for i in range(10)]) 
ndb.put_multi([Foo(parent=bar) for bar in bars]) 

futures = [Foo.query(ancestor=bar).fetch_async(10) for bar in bars] 
for f in futures: 
    print(f.get_result()) 

這將啓動10點併發數據存儲區查詢的RPC和整體延遲僅取決於最慢的一個,而不是所有的等待時間的總和

有關如何使用ndb異步API的更多詳細信息,請參閱官方ndb documentation

+0

看看我編輯的代碼...是否有可能使它比我正在做的更異步,或者我達到了最大值? – Snowman